我正在嘗試定義一個可以包裝任意函式同時保留引數型別和回傳型別的函式。當函式沒有泛型時,我讓它作業,但我正在努力讓它與泛型一起作業。這是一個簡化的示例:
function wrap<F extends (...args: any[]) => any>(test: F) {
return (...args: Parameters<typeof test>): ReturnType<typeof test> => {
return test(...args);
};
}
function simpleTest(a: number): number {
return a;
}
// works
// type: (a: number) => number
const wrappedSimpleTest = wrap(simpleTest);
function genericTest<T>(a: T): T {
return a;
}
// doesn't work
// type: (a: unknown) => unknown
// desired type: <T>(a: T) => T
const wrappedGenericTest = wrap(genericTest);
function genericTest2<T, U>(a: T, b: U): T|U {
return Math.random() < 0.5 ? a : b;
}
// doesn't work
// type: (a: unknown, b: unknown) => unknown
// desired type: <T, U>(a: T, b: U) => T|U
const wrappedGenericTest2 = wrap(genericTest2);
uj5u.com熱心網友回復:
您在此處尋找的特定行為可以通過使用 TypeScript對泛型函式的高階型別推斷的支持來實作,在microsoft/TypeScript#30215中實作。一般來說,該語言無法在型別系統中以這種方式抽象泛型;這將需要microsoft/TypeScript#1213中要求的更高種類的型別,而 TypeScript 沒有。相反,它使用一些具有一些特定限制和要求的啟發式方法來嘗試以這種方式推斷通用函式型別。
這是使其作業的一種方法:
function wrap<A extends any[], R>(test: (...args: A) => R) {
return (...args: A): R => {
return test(...args);
};
}
const wrappedGenericTest = wrap(genericTest);
// const wrappedGenericTest: <T>(a: T) => T ??
const wrappedGenericTest2 = wrap(genericTest2);
// const wrappedGenericTest2: <T, U>(a: T, b: U) => T | U ??
我F用一對型別引數替換了您的型別引數,A并R對應于引數和回傳型別。F在這里使用的問題是實用Parameters<T>程式型別和實用程式型別是條件型別,編譯器會丟失泛型。ReturnType<T>
通過直接使用Aand R,編譯器可以跟蹤高階型別操作,并獲得所需的泛型函式型別。
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/454822.html
標籤:打字稿
