【问题标题】:Extend indexed typescript interface扩展索引打字稿接口
【发布时间】:2018-10-12 23:07:52
【问题描述】:

考虑一个简单的索引接口:

interface FormData {
    [K: string]: string;
}

那个小家伙工作得很好。但是,有一种情况我想允许一个属性是一个字符串数组。

interface AcmeFormData extends FormData {
    foobar: string[];
}

Typescript 抱怨

“string[]”类型的属性“foobar”不能分配给字符串索引类型“string”。

查看文档,似乎以下应该是可能的,但也有抱怨。

interface FormData {
    [K: string]: string;
    foobar: string[];
}

应该注意的是,我希望避免使用联合类型 ([K: string]: string | string[];),因为 99% 的时间,数据将始终是单个字符串值,因此希望避免键入提示。

这可能吗?还是我想滥用 Typescript?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您可以通过使用交叉点而不是使用extends 来做到这一点。例如:

    interface FormData {
        [K: string]: string;
    }
    
    type AcmeFormData = FormData & { foobar: string[] };
    
    declare const test: AcmeFormData;
    
    test.foobar       // string[]
    test.anythingelse // string
    

    但是,这确实会导致一些您需要小心的问题,因为现在索引签名不再准确。因此,当 typescript 使用该签名推断某些内容时,您需要注意这将是错误的:

    for (let key in test) {
        // val is inferred to have type string, but be careful!
        // In truth, val will be a string[] for the 'foobar' key,
        // but typescript is no longer aware of that. So this will
        // create a runtime error, but compiles without problems!
    
        const val = test[key].toLowerCase();
    }
    

    【讨论】:

      【解决方案2】:

      这不起作用的原因是因为[K: string]: string表示接口中每个键的值必须是字符串,而foobar包含在每个键中。我建议改为这样做:

      interface FormData {
        fields: { [field: string]: string }
        somethingElse: string[]
      }
      

      【讨论】:

      • 有没有办法放松一点,让 [field:string]:string|number 管道注释一个假设的运算符合并两种类型。能解决吗?
      猜你喜欢
      • 2019-05-04
      • 2019-01-20
      • 2021-05-20
      • 2022-01-20
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      相关资源
      最近更新 更多