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>'.
 }
}
1

There are 1 best solutions below

0
On

Your problem here is that polymorphic this behaves like a generic type parameter, and inside the implementation of Test, 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 of Test instead of implementing it, the compiler will substitute Test for this and all will behave as expected, like

new Test().withArgKeyOfTypeBoolean("boolProp"); // okay

That leads to a possible workaround: inside try(), first assign the (generic-like) this to the (specific) Test, and then call withArgKeyOfTypeBoolean() on that:

try(): void {
    const thisTest: Test = this;
    thisTest.withArgKeyOfTypeBoolean('boolProp'); // okay
}

Playground link to code