I'm trying to write a generic class that is passed a key key corresponding to a key of one of a set of known interfaces on construction and that can later be passed an object thing and type-safely access thing[key]. This is what I've got:
interface AB {
a: string
b: number
}
interface BC {
b: number
c: Date
}
type ABC = AB | BC
class Getter<T extends ABC> {
key: keyof T;
constructor(key: keyof T) {
this.key = key;
}
get(thing: T): string {
const value = thing[this.key];
return value.toString();
}
}
const getter = new Getter<AB>('b');
Playground Link
Here, I'd expect Typescript to infer that because T extends ABC that T[keyof T] = AB[keyof AB] | BC [keyof BC] = string | number | date. However, it seems to get stuck at T[keyof T]. Even adding an as AB[keyof AB] | BC[keyof BC] to that line doesn't fix it, I need as unknown as AB[keyof AB] | BC[keyof BC]! Is there any way to get this working without that line?
Also, is there any way I could parameterize over the value of key as a type instead of parameterizing over the type of thing?
When T extends ABC, it can have many other properties and types. Which can therefore not have .toString() method.
type G = {
a: string;
b: number;
hello: undefined;
};
const g = new Getter<G, keyof G>("hello");
g.get({
a: "a",
b: 1,
hello: undefined
}); // undefined does not have .toString() method
Playground Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With