泛型函式語法有什么區別:
type Identity<T> = (t: T) => T
和
type Identity = <T>(t: T) => T
?
uj5u.com熱心網友回復:
TypeScript中有兩種不同風格的泛型:泛型函式和泛型型別。
泛型函式在函式的呼叫簽名上宣告其泛型型別引數(或多個引數):
type IdentityGenFunc = <T>(t: T) => T
在實際呼叫函式之前,不會指定泛型函式(T上面)的型別引數,此時呼叫者指定它(或編譯器代表呼叫者推斷它)。這意味著通用函式實作必須能夠處理T函式呼叫者想要的任何可能的規范:
const idGenFunc: IdentityGenFunc = x => x;
const resultABC = idGenFunc("ABC"); // T inferred here as ABC
// const resultABC: "ABC"
const result123 = idGenFunc(123); // T inferred here as 123
// const result123: 123
泛型型別在型別宣告中宣告其泛型型別引數(或多個引數):
type IdentityGenType<T> = (t: T) => T
必須先指定泛型型別(T上面)的型別引數,然后才能獲得該型別的值。如果泛型型別具有參考型別引數的呼叫簽名或方法,則在呼叫該方法之前,一旦指定了周圍的泛型型別,該型別引數就會被固定。比如說,一旦你在談論 an IdentityGenType<string>,那么它的呼叫簽名只需要能夠處理 a string。因此,要實作該功能,您不需要處理任何可能的值T:
const idGenTypeString: IdentityGenType<string> = x => x "!";
const resultABCagain = idGenTypeString("ABC"); // okay, "ABC" is assignable to string
// const resultABCagain: string
const result123Again = idGenTypeString(123); // error! 123 is not assignable to string
這兩種泛型是相互關聯的。該型別IdentityGenFunc本質上是IdentityGenType<T>每個可能的“無限交集” T。TypeScript 型別系統的表現力不足以說明這一點:
// the following is not valid TS, but this is what you want to say
type IdentityGenFunc = forall T, IdentityGenType<T>; // not valid TS, error
但你可以通過作業見證它:
// every IdGenFunc is also an IdGenType<number>
const idGenTypeNumber: IdentityGenType<number> = idGenFunc; // okay
另一方面,您可以將其視為與某種型別的實體化IdentityGenType<T>相同。同樣,型別系統不會讓您表達這一點:IdentityGenFunc T
// the following is not valid TS, but this is what you want to say
type GenType<T> = instantiate GenFunc with T; // not TS, error
盡管 TypeScript 4.7 將引入實體化運算式,它允許您在型別為泛型函式的值上實體化型別引數:
// if you instantiate a value of type IdGenFunc with Date, then you get an IdGenType<Date>
const idGenTypeDate: IdentityGenType<Date> = idGenFunc<Date>; // okay for TS4.7
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/477882.html
上一篇:在函式中使用非單態泛型引數
