【问题标题】:TypeScript index signatures class implementationTypeScript 索引签名类实现
【发布时间】:2019-05-19 16:58:22
【问题描述】:

考虑下面的代码 sn-p:

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

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

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

嘿,IProduct 接口可以是任何类型的对象 可以是以下类型之一的字段数: numberboolean。现在实现这个接口的类 基本上可以包含完全相同的字段变化

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

export class Product implements IProduct {
    [key: string]:  number | boolean;
    b: number;
    c: boolean;
}

但老实说,我的期望是我可以只声明类字段,只要它们符合接口声明合同,我就不会收到如下错误:

export class Product implements IProduct {
    b: number;
    c: boolean;
    a: string /* Gives erorr, since string is not allowed index type */
}

关于如何绕过这个或只是我的理解完全错误的任何想法?

【问题讨论】:

    标签: typescript


    【解决方案1】:

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

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

    【讨论】:

    • 我不希望任何人回答除了你的 Titan :)
    • @Tomas :)) 我在这里花了很多时间 :)
    猜你喜欢
    • 2020-02-21
    • 2018-02-23
    • 2019-04-06
    • 2023-03-13
    • 2013-01-28
    • 2018-09-15
    • 2020-02-02
    • 2020-02-15
    • 1970-01-01
    相关资源
    最近更新 更多