iT邦幫忙

2024 iThome 鐵人賽

DAY 26
1
JavaScript

TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?系列 第 26

第26關:Append Argument!TypeScript 變形金剛:參數拼裝車

  • 分享至 

  • xImage
  •  

第26關:Append Argument

關卡簡介

For given function type Fn, and any type A (any in this context means we don't restrict the type, and I don't have in mind any type 😉) create a generic type which will take Fn as the first argument, A as the second, and will produce function type G which will be the same as Fn but with appended argument A as a last one.

對於給定的函數類型 Fn,以及任何類型 A(這裡的“任何”是指我們不限制這個類型,我也沒有具體想到哪種類型 😉),創建一個泛型類型,它將接受 Fn 作為第一個參數,A 作為第二個參數,並生成函數類型 GG 將與 Fn 相同,但會在最後追加一個 A 類型的參數。

任務說明:

type Fn = (a: number, b: string) => number

type Result = AppendArgument<Fn, boolean> 
// expected be (a: number, b: string, x: boolean) => number

接下來,你的任務是讓下面的type cases測試通過:

type Case1 = AppendArgument<(a: number, b: string) => number, boolean>
type Result1 = (a: number, b: string, x: boolean) => number

type Case2 = AppendArgument<() => void, undefined>
type Result2 = (x: undefined) => void

type cases = [
  Expect<Equal<Case1, Result1>>,
  Expect<Equal<Case2, Result2>>,
]

冒險指南:

從以下幾個方向來思考:

  • 類型推斷 (Type Inference):使用 TypeScript 的 infer 關鍵字來推斷函數的參數列表和返回值。在這裡,我們需要推斷出 Fn 函數的參數類型 P 以及返回值類型 R

  • 條件型別 (Conditional Types):這是 TypeScript 的一個功能,可以根據特定條件來確定類型。在這裡,我們使用 Fn extends (...arg: infer P) => infer R 來檢查 Fn 是否為一個函數,並且提取它的參數類型 P 和返回值 G

  • 參數展開 (Parameter Spread):利用 TypeScript 的展開運算符 ...,可以將函數的參數類型擴展成一個數組。在這裡,我們將推斷出的參數類型 P 展開,並在末尾添加類型 A 作為新的參數。

通關方式:

解法:

type AppendArgument<Fn extends (...arg: any[]) => unknown, A> = Fn extends (
        ...arg: infer P
    ) => infer G
        ? (...arg: [...P, A]) => G
        : never

細節分析:

  • 類型限制 (Strict Type Constraints) type AppendArgument<Fn extends (...arg: any[]) => unknown, A>`` 這種寫法更嚴謹,因為它要求 Fn必須是一個函數類型(…arg: any[]) => unknown`。這樣可以在有人意外傳遞非函數類型時,讓 TypeScript 提示錯誤,

  • 條件型別 (Conditional Types):Fn extends (...arg: infer P) => infer G 用來檢查 Fn 是否是一個函數,並提取它的參數類型 P 和返回值類型 G

  • 參數推斷 (Parameter Inference):利用 infer P 提取函數的參數類型,infer G 提取返回值類型。這使我們能夠動態地操作 Fn 的參數。

  • 參數組合 (Parameter Concatenation):[...P, A] 是用來將原始的參數類型展開,並在末尾追加新的參數類型 A。這樣就生成了帶有新參數的函數類型。我們使用了 元組 (Tuple) 的展開語法。P 是一個元組,這裡的 A 是一個新的元素。這個語法的含義是 arg 參數將會是一個包含了 P 中所有元素,並在最後附加一個 A 的元組。
    例如,如果 P[number, string],而 Aboolean,那麼 ...arg 的類型會是 [number, string, boolean]

  • 函數返回值保持不變:函數的返回值類型 G 保持不變,這確保了新生成的函數仍然符合原始的輸出預期。

這樣,我們就能順利通過測試啦 🎉 😭 🎉

總結:

本次介紹了 Append Argument 的實作,下一關會挑戰 Permutation,期待再相見!


上一篇
第25關:ReplaceAll!TypeScript 中忍替身術:變換全部字串
下一篇
第27關:Permutation!TypeScript 黑板上排列組合:你捨得解開嗎?
系列文
TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言