Reputation: 107
I have some types:
interface IMyParentInterface {
foo: string,
items: IMyChildinterface[]
}
interface IMyChildinterface {
id: number,
bar: string,
}
And I have a class which uses the interfaces:
class MyClass<T, D = keyof T> {...}
So, I'm creating the instance:
const class = new MyClass<IMyParentInterface, IMyChildinterface>(...)
So I want to strictly check if IMyChildinterface
is that exact type, that is used as a IMyParentInterface
property.
In other words, I shouldn't be able to do something like this:
const class = new MyClass<IMyParentInterface, TJustRandomType>(...)
Unfortunatelly, typeof
does nothing to make it work
Upvotes: 1
Views: 1524
Reputation: 20132
We need to restrict types to specific subsets by extends
keyword. Consider:
class MyClass<
T extends { items: any },
D extends T['items'][number] = T['items'][number]> { };
const a = new MyClass<IMyParentInterface, IMyChildinterface>(); //ok
interface Other {
a: string
}
const b = new MyClass<IMyParentInterface, Other>(); //error
Explanation:
T extends { items: any }
as you put there generic, I assume IMyParentInterface
is not one and only type you want to use. I am then restricting that our first type has items
propertyD extends T['items'][number] = T['items'][number]
- restriction that second type will be the type from the first items
property item type.// proposition with picking the property
class MyClass<
Prop extends PropertyKey,
T extends Record<Prop, any>,
D extends T[Prop][number] = T[Prop][number]> { }
const a = new MyClass<'items', IMyParentInterface, IMyChildinterface>(); //ok
interface Other {
a: string
}
const b = new MyClass<'items', IMyParentInterface, Other>(); //error
// proposition with every array type property
type PickByValue<T, V, _Keys extends keyof T = {
[K in keyof T]: T[K] extends V ? K : never
}[keyof T]> = Pick<T, _Keys>
class MyClass<
T extends (Array<any> extends T[keyof T] ? object : never),
D extends _E[keyof _E][number],
_E extends Record<any, Array<any>> = PickByValue<T, Array<any>>
> { }
const a = new MyClass<IMyParentInterface, IMyChildinterface>(); //ok
interface Other {
a: string
}
const b = new MyClass<IMyParentInterface, Other>(); //error
Upvotes: 2