TypeScript索引签名类的实现

时间:2018-12-19 08:26:03

标签: typescript

请考虑以下代码段:

id('')

我希望TypeScript能够像下面这样理解:

  

嘿,id(0)接口可以是具有任何对象的任何对象   可以通过以下类型之一的字段数:   // Model: Father public class Father { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id{get;set;} public string Name{get;set;} } // Model: Child public class Child { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id{get;set;} public string Name{get;set;} public Father MyFather{get;set;} } Child child = new Child { Name="childName", MyFather = new Father { Name="fatherName" }; }; db.saveChild(child); 。现在,实现此接口的类   基本上可以包含完全相同的字段变化

不幸的是,上面的代码给了我错误,该类无法正确实现接口,迫使我将索引类型重新输入到类本身中:

export interface IProduct {
    [key: string]: number | boolean;
}

export class Product implements IProduct {
    b: number;
    c: boolean;
}

但是说实话,我的期望是,我只能声明类字段,只要它们符合接口声明约定,我就不会出现以下错误:

IProduct

关于如何绕过这个问题或我的理解的任何想法都是错误的吗?

1 个答案:

答案 0 :(得分:3)

您可以创建一个类型,以强制执行所需的约束,但必须是映射类型:

export type IProduct<T> = Record<keyof T, number | boolean>
// Or, same effect but using the actual mapped type
// export type IProduct<T> = {
//    [P in keyof T]: number | boolean;
//}

export class Product implements IProduct<Product> {
    b: number;
    c: boolean;
}

打字稿抱怨的原因是接口索引签名将允许您使用任何字符串进行索引,但是类仅具有特定的键。如果您的课程确实可以有任何键,那么它应该具有索引签名以使其明确。

修改

不同版本,其中接口的泛型类型参数是接口将具有的键:

export type IProduct<T extends PropertyKey> = Record<T, number | boolean>

export class Product implements IProduct<keyof Product> {
    b: number;
    c: boolean;
}
let o: IProduct<'c' | 'b'> = new Product();
相关问题