简体   繁体   English

Typescript:允许泛型类型只是具有'string'属性的对象

[英]Typescript: allow a generic type to only be an object with 'string' properties

I am wondering if it is possible in TS to enforce the type of the properties for a generic. 我想知道在TS中是否可以强制执行泛型的属性类型。 I would like to only allow passing a generic of an object type with 'string' properties. 我想只允许传递带有'string'属性的对象类型的泛型。 Raise an error if for instance the passed generic interface would contain number or symbols properties. 如果传递的通用接口包含数字或符号属性,则引发错误。

Here is a POC of what I tried and commented the behaviour I am looking for: 这是我尝试过的POC ,并评论了我正在寻找的行为:

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

Note 注意

If you don't have any other constraints on the values of T a simple object type would work as well 如果对T的值没有任何其他约束,则简单object类型也可以

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

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

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