如果事件的資料不是未定義的,我如何鍵入可以選擇具有第二個引數的函式?
例如:
type Events = {
a: { bc: number }
d: undefined
}
type Fn<T extends Record<string, unknown>> = <E extends keyof T>(event: E, data: T[E]) => void
const fn: Fn<Events> = getFN();
當有人呼叫fn('a')Typescript 時會正確拋出錯誤,因為{ bc: number }沒有提供。但是,fn('d')會拋出錯誤,因為打字稿期望fn('d', undefined).
如何取消供應要求undefined的fn('d')?
uj5u.com熱心網友回復:
如果函式引數是optional,則它將接受undefined作為值。但反過來不一定正確。僅僅因為函式引數接受undefined它并不意味著它是可選的。如果你想要一個undefined型別T[E],使data一個可選的引數,那么你的Fn型別需要進行更多復雜的; 函式引數本身需要依賴,T[E]而不僅僅是它們的型別。
這是一種方法:
type Fn<T extends Record<string, unknown>> = <E extends keyof T>(
event: E, ...rest: undefined extends T[E] ? [data?: T[E]] : [data: T[E]]
) => void
現在該Fn型別是一個泛型函式,它的第一個引數是型別E,之后其余引數的陣列是依賴于的條件型別T[E]。
讓我們來看看把條件型別:undefined extends T[E] ? [data?: T[E]] : [data: T[E]]。因此,如果屬性型別T[E]接受undefined,則引數串列的其余部分是一個元組,其中包含一個帶有標簽的可選元素。如果屬性型別并不能接受,那么引數串列的其余部分是一個元組所需的元素,也標示。這意味著無論如何,我們正在構建一個雙引數函式型別,但如果接受 undefined,第二個引數將是可選的。 dataT[E]undefineddataT[E]
讓我們試試看:
declare const fn: Fn<Events>;
fn('a'); // error, expected 2 elements, got 1
/* const fn: <"a">(event: "a", data: { bc: number; }) => void */
fn('a', { bc: 123 }); // okay
fn('d') // okay
/* const fn: <"d">(event: "d", data?: undefined) => void */
這一切都按預期進行。當您使用IntelliSense觀察 的型別時fn('a', ...),您會看到它有兩個引數,其中第二個引數是 named data、 required 和 type {bc: number}。fn('d', ...)另一方面,當您呼叫 時,第二個引數也被命名為data,但它是可選的且型別為undefined。所以現在你會在你期望的地方并且只在你期望的地方出錯。
如果傳遞給的型別Fn具有可選屬性,則這將自動成為data相同型別的可選引數:
declare const o: Fn<{ opt?: string }>
o('opt', "str"); // okay
o('opt'); // also okay
看起來挺好的。
Playground 鏈接到代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/382653.html
標籤:打字稿
