擴展索引型 TypeScript 介面
考慮一個簡單的索引介面:
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?
答案#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[]
}
