[英]TypeScript `string literal` subsets not assignable to full set in overloaded function
嘗試為鍵入的鍵值對創建映射 function:
type Color = {
"Red": number,
"Green": string
"Yellow": boolean
"Purple": object
};
type PropMapping = {
"Apple": Pick<Color, "Red" | "Green">,
"Banana": Pick<Color, "Yellow" | "Green">,
"Grape": Pick<Color, "Purple" | "Green">
}
function map(key: "Apple"): Pick<Color, "Red" | "Green">;
function map(key: "Banana"): Pick<Color, "Yellow" | "Green">;
function map(key: "Grape"): Pick<Color, "Purple" | "Green">;
function map(key: keyof PropMapping): Partial<Color> {
// perform actual mapping in here (e.g. via switch-case)
return {};
}
稍后我嘗試使用此映射 function,但使用Color
類型的子集
// type of fruits is a subset of `keyof PropMapping`
const fruits: (keyof Pick<PropMapping, "Apple" | "Banana">)[] = ["Apple", "Banana", "Banana"];
// call the mapping function on each fruit
const colors: Partial<Color>[] = fruits.map(fruit => map(fruit));
但是,在調用map(fruit)
時出現以下錯誤:
No overload matches this call.
The last overload gave the following error.
Argument of type '"Apple" | "Banana"' is not assignable to parameter of type '"Grape"'
Type '"Apple"' is not assignable to type '"Grape"'.
對我來說似乎很奇怪,因為fruit
參數是可以傳入的可能 fruits 的子集。在不使用as
關鍵字的情況下無法使此映射 function 重載工作(需要as
對我來說有點代碼味道)。
我希望能夠從一個或多個Partial<Color>
重建Color
。 例如,假設我這樣做:
const redGreen = map("Apple");
const yellowGreen = map("Banana");
const purpleGreen = map("Grape");
const allColors: Color = {
...redGreen,
...yellowGreen,
...purpleGreen
};
上面的工作原理為 TypeScript 可以推斷聚合的Color
對象的屬性都在那里。 但是,我想保持聚合Partial<Color>
對象的能力,如上例所示:
const colors: Partial<Color>[] = fruits.map(fruit => map(fruit));
這是讓我崩潰的部分
編輯:將Color
更改為 object 以改善 model 我的情況(並使其他人更容易復制粘貼到他們自己的 IDE 中
EDIT2:修復重載返回類型
EDIT3: (keyof Pick<PropMapping, "Apple" | "Banana">)[]
...哦天哪。 謝謝大家指出這些
TypeScript 不支持同時調用多個重載簽名。 可以想象,編譯器可以通過允許 arguments 的並集然后返回返回類型的並集來支持解析此類調用,但這不是一個功能,至少目前如此。 有關此類支持的公開建議,請參閱microsoft/TypeScript#14107 。
除非並且直到它得到支持,否則如果您希望編譯器理解這種調用,則需要重構您的代碼。 您可以為每個可能的預期參數集添加一個調用簽名,但這僅適用於少數初始重載集,因為如果您從n 個不相交的調用簽名開始,您最終會得到 2 n 個合並的簽名。
對於您發布的將鍵映射到值類型的特定示例代碼,到目前為止,最直接的解決方案是放棄重載(或至少放棄多個調用簽名)以支持通用function,如下所示:
function map2<K extends keyof PropMapping>(key: K): PropMapping[K];
function map2(key: keyof PropMapping): Color {
return null!;
}
在這里, map2
將泛型類型K
的key
參數限制為您的PropMapping
類型的鍵,並返回PropMapping[K]
,即您在PropMapping
object 中查找K
鍵時獲得的值的類型。
然后你的數組調用應該工作:
const colors = fruits.map(fruit => map2(fruit));
// const colors: (Pick<Color, "Red" | "Green"> | Pick<Color, "Green" | "Yellow">)[]
好的,希望有所幫助; 祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.