Implement the built-in
Parameters
generic without using it.
不使用內建的 Parameters
泛型,實作其功能
(我們希望使用 MyParameters
泛型 (generic) 來提取任意函式 (function) 的參數型別 (parameter types),讓它返回對應的參數型別列表 (list of parameter types)。)
const foo = (arg1: string, arg2: number): void => {}
type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
接下來,你的任務是讓下面的type cases測試通過:
type cases = [
Expect<Equal<MyParameters<typeof foo>, [string, number]>>,
Expect<Equal<MyParameters<typeof bar>, [boolean, { a: 'A' }]>>,
Expect<Equal<MyParameters<typeof baz>, []>>,
]
從以下幾個方向來思考:
解法:
type MyParameters<T extends (...args:any) => unknown> = T extends (...arg: infer A) => unknown ? A : never
細節分析:
泛型參數 (Generic Parameters):
T extends (...args: any) => unknown
:這裡的 T 被限制為一個函式型別,它接受任何參數 (any) 並返回一個未知值 (unknown)。Parameters
泛型專門用來提取函式的參數型別。條件型別與推斷 (Conditional Types and Inference):
T extends (...arg: infer A) => unknown
,我們利用 infer
關鍵字來推斷出函式的參數列表 A。T
符合這個條件 (T
是函式),則會推斷出參數列表 A
並返回它;如果不符合條件,則返回 never。Parameters
的功能。遞迴與停止條件 (Recursion and Stopping Conditions):
T
不是函式型別時,返回 never
,這相當於處理異常或不匹配的情況,確保函式參數列表提取的正確性。infer A
會自動推斷為 [],這樣就處理了函式沒有參數的情況。這樣,我們就能順利通過測試啦 🎉 😭 🎉
這是初版解法,想了想不夠好,為什麼呢?
缺乏明確的型別限制 (Lack of Clear Type Restriction)
type MyParameters0<T> = T extends (...arg: infer A) => unknown ? A : never
在這段代碼中,雖然使用 MyParameters0<T>
也不會報錯,但這種寫法其實不夠嚴謹,原因在於對 T
的約束過於寬泛。在 MyParameters0<T>
中,T
可以是任何型別,沒有任何限制或條件。也就是說,T 不一定非得是函式型別,這會導致該泛型對不應用於函式的型別也能通過編譯,但這不是我們的想要的行為。
未來補充 😭
本次介紹了 Parameters
的實作,下一關會挑戰 Get Return Type
,期待再相見!