Reputation: 36273
I have a simple class that allows setting and getting generic values to a class object (imagine that this class is provided by an NPM package).
class Spec {
protected data = {};
set<T>(k: string, v: T) {
this.data[k] = v;
}
get(k: string) {
return this.data[k];
}
}
Let's say I create an instance of this class and set an id
field of type number
:
const spec = new Spec();
spec.set('id', 100);
When I retrieve this value, TypeScript returns the value as type any
instead of number
:
const id = spec.get('id');
// id should be of typescript type number (any instead)
I can manually specify the type but I would like to get handled this automatically:
const id = spec.get<number>('id');
// or
const id = spec.get('id') as number;
Is there a hack for this situation?
Upvotes: 1
Views: 63
Reputation: 250246
The one way I can think of is if Spec
had a generic parameter to represent the type for data
and when set
is called, this
is returned but with it's type modified to reflect the newly added field. The problem with this approach is that you need to either make all the calls to set
before assigning the value to a variable, or hold each subsequent result of set
in a new variable as it will have a different type.
class Spec<TAll = {}>{
protected data: TAll = {} as any;
set<TKey extends string, TValue>(k: TKey, v: TValue): Spec<TAll & { [P in TKey]: TValue }> {
(this.data as any)[k] = v;
return this as any
}
get<TKey extends keyof TAll>(k: TKey) {
return this.data[k];
}
}
const spec = new Spec().set('id', 100);
spec.get('id') // is number
Upvotes: 1