簡體   English   中英

通用參數的聯合類型

[英]Union type for generic param

代理返回條件隨機類型。

const numbersArray = [1,2,3,4];
const stringsArray = ['1','2','3','4'];


function func<T>(array: T[]): T[][] {
  return [[array[0], array[1]], [array[2], array[3]]];
}

const proxy = () => Math.random() < 0.5 ? numbersArray : stringsArray;

const resulNumbers = func(numbersArray);

const resultStrings = func(stringsArray);

const resultUnion = func(proxy()); // error

錯誤

const proxy: () => number[] | string[]

Argument of type 'number[] | string[]' is not assignable to parameter of type 'number[]'.
  Type 'string[]' is not assignable to type 'number[]'.
    Type 'string' is not assignable to type 'number'.(2345)

鏈接到游樂場

解決這個問題的正確方法,有什么想法嗎?

這個 function:

const proxy = () => Math.random() < 0.5 ? numbersArray : stringsArray;

返回類型為:

number[] | string[]

這種類型表示您要么有一個所有數字的數組,要么有一個所有字符串的數組,但絕不是兩者的混合。

那么該類型的成員的類型是什么? 你可能認為它是number | string number | string ,但這並不完全正確。 如果你拿string | number string | number並將數組符號添加到末尾,您將獲得:

(number | string)[]

這種類型表示它是一個字符串或數字數組,每個成員都可以是。 您現在可以將兩者混合使用。 這不是一回事。 這意味着無法推斷成員類型,因為該成員類型不能用於構造原始數組類型。

現在讓我們看看通用的 function:

function func<T>(array: T[]): T[][] {
  return [[array[0], array[1]], [array[2], array[3]]];
}

這個 function 試圖找到數組T[]的成員類型T 但如上所示, string[] | number[]沒有好的成員類型。 string[] | number[] 所以 typescript 無法推斷T並拋出錯誤。

因此,要使您的 function 工作,成員類型T需要是可推斷的。 您可以通過將代理的返回類型轉換為兼容的數組類型來做到這一點,其中只有數組的成員是聯合。

const proxy: () => (string | number)[] =
  () => Math.random() < 0.5 ? numbersArray : stringsArray;

現在T可以變成string | number string | number和一切都像你期望的那樣工作。

const resultUnion = func(proxy()); // type: (string | number)[][]

操場

發生錯誤是因為類型參數T如何解析對func的調用。 proxy的返回類型是

number[] | string[]

並根據number[] | string[]的方式推斷T的類型 number[] | string[]符合以下簽名:

function func<T>(x: T[]): T[][]

所以x必須是T的數組,就func而言,它可以是任何類型。 number[] | string[]的情況下 number[] | string[] T的類型被推斷為number ,因為number[]是聯合中第一個與xT[]匹配的類型。 不幸的是,沒有考慮到string[]

您可能希望Tnumber | string 此調用的number | string ,您可以通過在調用func時顯式指定類型來做到這一點:

const xs: (number | string)[][] = func<number | string>(proxy())

這個重復的問題的答案解釋了為什么 TypeScript 並不總是推斷泛型類型參數的聯合; 這是因為當調用者為單個泛型類型參數指定多個事物時,它通常表示錯誤,並且如果編譯器總是在這種情況下推斷出一個聯合,它將允許很多可能錯誤的代碼。 有關此問題的“官方”討論,請參見microsoft/TypeScript#19656

無論如何,在您的情況下,我可能會將func()簽名更改為:

function func<T extends any[]>(array: T): T[number][][] {
  return [[array[0], array[1]], [array[2], array[3]]];
}

在這種情況下, T實際上是傳入數組的類型,而不是其成員的類型,即T[number] 我想這應該對你有用。

希望有幫助; 祝你好運!

Playground 代碼鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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