Reputation: 41
We have created the following type according to this post : https://stackoverflow.com/a/49752227
export type KeysOfType<T, TProp> = { [P in keyof T]: T[P] extends TProp? P : never}[keyof T];
In this example
class A {
public prop1: number;
public prop2: string;
public prop3: string;
}
class B<O extends A>
{
private prop: KeysOfType<O, string>;
private prop2: KeysOfType<A, string>;
public method(): void
{
let o: O;
let notTypedAsString = o[this.prop];
let a: A;
let typedAsString = a[this.prop2];
}
}
The expression o[this.prop]
is not typed as string despite the fact that this.prop
is typed as a "string" property of O.
Link to the playground
Is there a way to make it work ?
Upvotes: 4
Views: 626
Reputation: 249466
The answer you cite (always nice to be cited :) ) works well for usage site. So when you use the class or the function that uses KeysOfType
you will get the expected behavior. The problem is that inside the class or function where the generic type is not known, typescript can't reason about what the indexing operation will produce.
We can use an approach similar to here. Where the generic parameter itself extends something that only has string keys (Record<K, string>
). We will need an extra parameter K
to capture only the string keys of the O
type but it all works as expected:
export type KeysOfType<T, TProp> = { [P in keyof T]: T[P] extends TProp ? P : never }[keyof T];
class A {
public prop1: number;
public prop2: string;
public prop3: string;
}
class B<O extends Record<K, string> & A, K extends string | number | symbol = KeysOfType<O, string> >
{
constructor() {
}
private prop: K;
private prop2: keyof A
public method(): void {
let o!: O;
let notTypedAsString = o[this.prop]; // if you hover over it it will be O[K]
notTypedAsString.bold();//but it behaves as string
o.prop1 // number, A memebrs that arae not strings still work as expected
}
}
new B<A>()
class A2 extends A {
public prop4: number;
public prop5: string;
}
new B<A2>()
Upvotes: 1