简体   繁体   English

是否可以将泛型类型约束为TypeScript中keyof的子集?

[英]Is it possible to constrain a generic type to be a subset of keyof in TypeScript?

In the current version (2.1) of TypeScript I can constrain a method argument on a generic class to be a property of the generic type. 在TypeScript的当前版本(2.1)中,我可以将泛型类的方法参数约束为泛型类型的属性。

class Foo<TEntity extends {[key:string]:any}> {
    public bar<K extends keyof TEntity>(key:K, value:TEntity[K]) { }
}

Is it possible in the current type system to constrain the key part even further to be a subset where the value of the key is of a certain type? 在当前类型系统中是否有可能将关键部分进一步限制为密钥值为某种类型的子集?

What I'm looking for is something along the lines of this psuedo code. 我正在寻找的是这个伪代码的东西。

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);
    }
}

EDIT 编辑

For clarification I added a more complete example of what I'm trying to achieve. 为了澄清,我添加了一个更完整的例子来说明我正在努力实现的目标。

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);
    }
}

Demo on typescriptlang.org 在typescriptlang.org上演示

convertText will give an error saying that Type 'string' is not assignable to type 'T[K]' . convertText将给出一个错误,指出convertText Type 'string' is not assignable to type 'T[K]'

Given 特定

interface Foo {
    s: string
    n: number
}

The compiler can tell that this will work 编译器可以告诉它这将工作

this.convert('s', 123, v => String(v));

and this will not 这不会

this.convert('n', 123, v => String(v));

I'm hoping I can constrain the convertText method to keys where the value is of type string to get type safety on the key parameter. 我希望我可以将convertText方法约束到值为string类型的键,以获得key参数的类型安全性。

It is possible (using a non-class example here). 这是可能的(在这里使用非类示例)。 The following will ensure that T[P] is a string. 以下将确保T[P]是一个字符串。

function convertText<T extends {[key in P]: string }, P extends keyof T>(data: T, field: P & keyof T) {
    // ...
}

The idea is to narrow the type of T to only the fields inferred in P and set the exact type you want, in this case string . 我们的想法是将T的类型缩小到仅在P推断出的字段,并设置所需的确切类型,在本例中为string

Test: 测试:

let obj = { foo: 'lorem', bar: 2 };
convertText(obj, 'foo');
convertText(obj, 'bar'); // fails with: Type 'number' is not assignable to type 'string'.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM