簡體   English   中英

TypeScript `string literal` 子集不可分配給重載中的完整集 function

[英]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將泛型類型Kkey參數限制為您的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM