In the latest version (2.1) of TypeScript, I have the ability to restrict a method argument in a generic class to be a property of the generic type.
class Foo<TEntity extends {[key:string]:any}> {
public bar<K extends keyof TEntity>(key:K, value:TEntity[K]) { }
}
Now my question is, can we further constrain the key part so that it belongs to a subset where the value of the key is of a specific type?
I have provided pseudocode for what I am looking for below.
class Foo<TEntity extends {[key:string]:any}> {
public updateText<K extends keyof TEntity where TEntity[K] extends string>(key:K, value:any) {
this.model[key] = this.convertToText(value);
}
}
UPDATE
To clarify things, I have included a more comprehensive example to illustrate what I am trying to accomplish.
type object = { [key: string]: any };
class Form<T extends object> {
private values: Partial<T> = {} as T;
protected convert<K extends keyof T>(key: K, input: any, converter: (value: any) => T[K])
{
this.values[key] = converter(input);
}
protected convertText<K extends keyof T>(key: K, input: any)
{
this.values[key] = this.convert(key, input, this.stringConverter);
}
private stringConverter(value: any): string
{
return String(value);
}
}
See Demo on typescriptlang.org
The issue with convertText
arises when it says that
Type 'string' is not assignable to type 'T[K]'
.
For instance:
interface Foo {
s: string
n: number
}
The compiler determines that this will work:
this.convert('s', 123, v => String(v));
whereas this will not:
this.convert('n', 123, v => String(v));
My goal is to limit the convertText
method to keys where the value is of type string
in order to enforce type safety on the key parameter.