扩展索引打字稿界面

时间:2018-10-12 23:07:53

标签: typescript

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

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

那个小家伙真棒。但是,在某些情况下,我想允许一个属性为字符串数组。

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

打字稿抱怨

  

类型为'string []'的属性'foobar'无法分配给字符串索引类型'string'。

仔细阅读文档,似乎以下内容应该可行,但也会抱怨。

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

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

这可能吗?还是我想滥用打字稿?

2 个答案:

答案 0 :(得分:3)

之所以不起作用,是因为[K: string]: string表示接口中每个键的值必须是字符串,并且每个键都包含foobar 。我建议改做这样的事情:

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

答案 1 :(得分:3)

您可以通过使用交集而不是使用extends来实现。 EG:

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

type AcmeFormData = FormData & { foobar: string[] };

declare const test: AcmeFormData;

test.foobar       // string[]
test.anythingelse // string

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

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