簡體   English   中英

在 typescript 中,如何定義通用 function 的專用版本?

[英]in typescript, how to define a specialized version of a generic function?

如果我有一個通用的 function:

const f1 = <T>(x: T) => console.log(x)

我可以為 f1 定義一個專門的版本:

const f2 = (x: number) => f1(x)

然后 typescript 如果我這樣做會拋出一個錯誤:

f2('6')

但 f2 實際上是另一個調用 f1 的 function。

有沒有辦法將 f2 定義為 f1 的專用版本? 就像是:

const f2 = f1<number> // this doesn't work

您可以像這樣定義泛型類型

type Fn<T = any> = (x: T) => void

const f1: Fn = (x) => console.log(x)
const f2: Fn<number> = f1
f2('6') // Argument of type '"6"' is not assignable to parameter of type 'number'.

是一個工作游樂場的鏈接

我將更改您的示例 function 因為類型<T>(x: T)=>void對泛型類型參數沒有任何用處,實際上與(x: unknown)=>void相同,a具體 function 型。 相反,讓我們看一下<T>(x: T)=>T類型的 function ,它保留輸入類型並輸出相同類型的值,其中(x: unknown)=>unknown不夠:

const f1 = <T>(x: T) => (console.log(x), x);
// const f1: <T>(x: T) => T

const n: number = 6;
const sixNumber = f1(n); // const sixNumber: number

const s: string = "6";    
const sixString = f1(s); // const sixString: string

您要做的是采用通用 function f1並將其用作(x: number)=>number類型的具體 function f2 這是f1類型的擴展,因為<T>(x: T)=>T類型的每個 function 也是(x: number)=>number類型的 function ,反之亦然。 編譯器將此識別為有效的擴展,您可以自己將f2注釋為擴展類型:

const f2: (x: number) => number = f1; // no error
const sixNumberOkay = f2(n); // okay
const sixStringNotOkay = f2(s); // error! string is not number

所以這很好。

--

現在,正如您所指出的,您不能做的是采用f1的類型和類型number並自動生成f2的類型。 類型系統無法讓您表示類型參數的替換類型。 f1<number>typeof f1<number>均無效。 TypeScript 對更高種類的類型沒有足夠的支持來表達這一點,至少不是純粹在類型級別

在 TypeScript 3.4 中,TypeScript 引入了對從其他泛型函數推斷泛型函數的改進支持 因此,雖然您不能僅在類型級別上進行您所詢問的類型操作,但您可以編寫一些函數讓編譯器無論如何都進行該操作。 例如:

function specify<A extends any[], R>(f: (...a: A) => R) {
    return () => f;
}

specify() function 接受任何 function,即使是通用的,並返回一個新的零參數 function,如果原始的也是通用的。 並且調用時 function 將返回原始 function。 這使您可以這樣做:

const f3 = specify(f1)<number>(); // const f3: (x: number) => number

specify(f1)返回類型為<T>() => (x: T) => T的 function 。 因此specify(f1)<number>()產生非通用(x: number)=>number function。 它也應該在運行時工作:

const sixNumberStillOkay = f3(n); // okay
const sixStringStillNotOkay = f3(s); // error! string is not number

我不確定您是否會經常將通用函數擴展到具體函數,以使specify()值得; 這取決於你。


好的,希望有幫助; 祝你好運!

鏈接到代碼

暫無
暫無

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

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