I have a base class with a method callable from derived classes where you supply one of the derived property names that must be of a specific type. The property value is then operated on. I want to be able to specify this specific type. ( keyof obviously is not sufficient )
Is it possible to type this ?
This does not work
type PropertyNamesOfType<T extends {},TPropertyType> = {
[P in keyof T]: TPropertyType extends T[P] ? P : never
}[keyof T]
declare class TypeUsingBoolPropertyOfDerived{
withArgKeyOfTypeBoolean<E extends PropertyNamesOfType<this, boolean>>(arg:E):void;
}
class Test extends TypeUsingBoolPropertyOfDerived{
boolProp:boolean
stringProp:string
try(): void {
this.withArgKeyOfTypeBoolean('boolProp');
//Argument of type 'string' is not assignable to parameter of type 'PropertyNamesOfType<this, boolean>'.
}
}
Your problem here is that polymorphic
this
behaves like a generic type parameter, and inside the implementation ofTest
,this
is an as-yet-unspecified/unresolved type parameter, and the compiler can't verify much about it. (There are some GitHub issues that mention this, at least in passing; see microsoft/TypeScript#41495, microsoft/TypeScript#41181)Outside
Test
, where you are just using an instance ofTest
instead of implementing it, the compiler will substituteTest
forthis
and all will behave as expected, likeThat leads to a possible workaround: inside
try()
, first assign the (generic-like)this
to the (specific)Test
, and then callwithArgKeyOfTypeBoolean()
on that:Playground link to code