0

Let me clear the question. I have an interface whose keys are tag names and the type of each key is the corresponding custom element class.

// custom element class
class View extends HTMLElement { ... }
abstract class ScrollLayout extends View { ... }
class ListView extends ScrollLayout { ... }
class GridView extends ScrollLayout { ... }

// Tag to Class
interface Tag2Class {
    "p-view": View;
    "p-list-view": ListView;
    "p-grid-view": GridView;
}

Now, I want to define another interface that has a key named layout whose type is the key of Tag2Class typed ScrollLayout

interface Attrs {
    layout?: ??? // I want the type to be "p-list-view" | "p-grid-view" | undefined
}

Is there a way to implement this? I tried Record<>

interface Attrs {
    layout?: keyof Record<keyof Tag2Class, ScrollLayout>;
}

But strangely, the type of layout also contains "p-view". I don't understand why the result came out like that because the Record type above would return the type { [P in keyof Tag2Class]: ScrollLayout }, and the keyof this would be only "p-list-view" | "p-grid-view".

Changdae Park
  • 911
  • 1
  • 9
  • 22
  • Why do you think `keyof Tag2Class` should not include p-view? It's one of the attributes of that interface. – sam256 Oct 07 '20 at 13:56
  • @sam256 I think so because `Record` itself constrains the type of `[P in keyof Tag2Class]` to be `ScrollLayout`. And `View` is not `ScrollLayout`. – Changdae Park Oct 07 '20 at 13:58
  • Record does not constrain. The two parameters to it are independent. So you are just defining a type with all the keys of Tag2Class and each having a type of ScrollLayout. That said, I think I understand your question--you want a type that only includes attribute names for types that extend ScrollLayout. Is that right? – sam256 Oct 07 '20 at 14:00
  • @sam256 Yeah! Do you have any idea? – Changdae Park Oct 07 '20 at 14:01

1 Answers1

2

You can use the KeyOfType from here to filter keys of a specific type:


type KeyOfType<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T]

interface Attrs {
    layout?: KeyOfType<Tag2Class, ScrollLayout> //  "p-list-view" | "p-grid-view" | undefined
}

Playground Link

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357