是否可以将泛型类型限制为 TypeScript 中 keyof 的子集? [英] Is it possible to constrain a generic type to be a subset of keyof in TypeScript?

查看:47
本文介绍了是否可以将泛型类型限制为 TypeScript 中 keyof 的子集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在当前版本 (2.1) 的 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.

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

编辑

为了澄清起见,我添加了一个更完整的示例来说明我要实现的目标.

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

typescriptlang.org 上的演示

convertText 将给出一个错误,指出 Type 'string' 不可分配给 type 'T[K]'.

convertText will give an error saying that Type 'string' is not assignable to type 'T[K]'.

给定

interface Foo {
    s: string
    n: number
}

编译器可以判断这会起作用

The compiler can tell that this will work

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

这不会

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

我希望我可以将 convertText 方法限制为值类型为 string 的键,以获得键参数的类型安全.

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.

推荐答案

这是可能的(此处使用非类示例).以下将确保 T[P] 是一个字符串.

It is possible (using a non-class example here). The following will ensure that T[P] is a string.

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

想法是将 T 的类型缩小到仅在 P 中推断的字段,并设置您想要的确切类型,在本例中为 string.

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.

测试:

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

这篇关于是否可以将泛型类型限制为 TypeScript 中 keyof 的子集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆