打字稿:允许泛型类型只能是具有“字符串"属性的对象 [英] Typescript: allow a generic type to only be an object with 'string' properties

查看:24
本文介绍了打字稿:允许泛型类型只能是具有“字符串"属性的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以在 TS 中强制执行泛型的属性类型.我只想允许传递具有字符串"属性的对象类型的泛型.例如,如果传递的通用接口包含数字或符号属性,则会引发错误.

I am wondering if it is possible in TS to enforce the type of the properties for a generic. I would like to only allow passing a generic of an object type with 'string' properties. Raise an error if for instance the passed generic interface would contain number or symbols properties.

这是一个 POC 我尝试并评论了我正在寻找的行为:

Here is a POC of what I tried and commented the behaviour I am looking for:

class Test<T extends {[key: string]: any}>{
    private data: T;

    public getValue<K extends keyof T>(key: K): T[K] {
        return this.data[key];
     }
}

// the property is a string = ok
const okay = new Test<{ "aString": string }>();

// the property is a number = should raise an error
const shouldFail = new Test<{ 0: string }>();

推荐答案

如果对象有字符串索引,我们也可以按数字索引对象,因此编译器没有理由抛出错误数字键.这是设计使然.

If the object has a string index we can index the object by number as well, so there is no reason for the compiler to throw an error number keys. This is by design.

declare let skeys: { [key: string]: number }
let v1 = skeys[0] // number 
let v2 = skeys["0"] // number

declare let nkeys: { [key: number]: number }
let v3 = nkeys[0] // number 
let v4 = nkeys["0"] // error 


declare let snkeys: {
    [key: number]: number;
    [key: string]: string | number // The string index has to contain any value reuned by the number index
}
let v5 = snkeys[0] // number 
let v6 = snkeys["0"] // string| number 

如果对象包含任何非字符串键,我们可以使用条件类型来强制错误.错误不会很漂亮,但它是可读的并且可以完成工作:

We can use a conditional type to force an error if the object contains any non-string keys. The error will not be very pretty, but it is readable and can get the job done:

class Test<T extends { [key: string]: any } & (keyof T extends string ? {} : "T must obnly have string keys") >{
    private data!: T;

    public getValue<K extends keyof T>(key: K): T[K] {
        return this.data[key];
    }
}

// the property is a string = ok
const okay = new Test<{ "aString": string }>();
// Error: Type '{ 0: string; }' does not satisfy the constraint '{ [key: string]: any; } & "T must only have string keys"'.
const shouldFail = new Test<{ 0: string }>();

注意

如果您对 T 的值没有任何其他限制,一个简单的 object 类型也可以使用

If you don't have any other constraints on the values of T a simple object type would work as well

class Test<T extends object & (keyof T extends string ? {} : "T must only have string keys") >{ }

这篇关于打字稿:允许泛型类型只能是具有“字符串"属性的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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