Reputation: 26075
Here's the sample code:
class Base {}
function fn<T extends typeof Base>(
Cls: T,
prop: keyof InstanceType<T>,
) {
return (new Cls())[prop];
}
prop
should be a property on Cls
, yet this code doesn't work?
It works if I change keyof InstanceType<T>
to keyof Base
, but I want the function to work with any subclass of Base
.
Upvotes: 3
Views: 903
Reputation: 33041
It is doable:
class Base {
base = 'base'
}
class A extends Base {
a = 'a'
}
class B extends Base {
b = 'b'
}
class C {
c = 'c'
}
const fn = <
T extends typeof Base,
Instance extends InstanceType<T>
>(Cls: new () => Instance, prop: keyof Instance,
) => new Cls()[prop];
const result = fn(A, 'base') // ok
const result2 = fn(B, 'b') // ok
const result3 = fn(Base, 'base') // ok
const result4 = fn(A, 'b') // expected error
const result5 = fn(B, 'a') // expected error
const result6 = fn(C, 'x') // expected error
Upvotes: 1
Reputation: 9893
There is no need to new Cls
And InstanceType
Try this one:
class Base {}
function fn<T extends typeof Base>(Cls: T,prop: keyof T) {
return Cls[prop];
}
Upvotes: 0
Reputation: 55856
There is a couple of problems here:
class Base {}
function fn<T extends typeof Base>(
Cls: T, // <--- Cls is already an instance of T
prop: InstanceType<T>, // <-- if you want properties of the class use keyof T
) {
return (new Cls())[prop]; // <-- You cannot call new on instance
}
With these in mind, this may work for you:
class Base {}
function fn<T extends Base>(
Cls: T,
prop: keyof T,
) {
return Cls[prop];
}
TS Playground: https://tsplay.dev/WJ9DDm
However, if you are passing the class to fn
and not the instance, the answer by Wang Weixuan fits better.
Upvotes: 0
Reputation: 351
It seems that TypeScript compiler reacts badly when InstanceType
is used on generics.
It works if you change the generic parameter to the instance type, which should be equivalent to original code:
function fn<T extends Base>(
Cls: new () => T,
prop: keyof T
) {
return new Cls()[prop];
}
Upvotes: 2