Implement a generic
Last<T>
that takes an Array T and returns its last element.
實作一個泛型 Last<T>
,它接受一個陣列 T
,並返回其最後一個元素。
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]
type tail1 = Last<arr1> // expected to be 'c'
type tail2 = Last<arr2> // expected to be 1
接下來,你的任務是讓下面的type cases測試通過:
type cases = [
Expect<Equal<Last<[2]>, 2>>,
Expect<Equal<Last<[3, 2, 1]>, 1>>,
Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>,
]
從以下幾個方向來思考:
infer
來從泛型中推導型別。...
(Spread Syntax) 把陣列分成前面的部分和最後的元素,然後用 infer
來推斷出最後一個元素的型別。T extends [...any, infer L]
:這樣的語法可以分割陣列,把最後一個元素取出來並賦值給 L
。這個方法無論陣列長度是固定還是可變,都適用。never
來避免錯誤。解法1:
type Last<T extends any[]> = T extends [...any, infer L] ? L : never
// 也可以改使用 _
type Last<T extends any[]> = T extends [...infer _, infer L] ? L : never
細節分析:
條件型別 (Conditional Types):條件型別允許根據不同的型別來執行不同的邏輯。在這裡,T extends [...any, infer L]
用於檢查 T
是否符合「一個陣列,且最後一個元素可以推斷為 L
」的條件。
T extends [...any, infer L]
表示 T
是一個包含任意數量元素的陣列,並且最後一個元素會被推斷為 L
。L
,否則返回 never
。型別推斷 (Type Inference):使用 infer
來從 T
中推斷最後一個元素的型別並將它賦值給 L
。這是 TypeScript 在處理陣列或元組中元素時常用的技巧,特別是當我們不知道具體的長度時。
infer L
會嘗試推斷出陣列的最後一個元素的型別,這就是我們想要的結果。省略元素 (Omitting Elements):在 T extends [...infer _, infer L]
中,...infer _
用來忽略陣列中的其他元素,只關注最後一個元素 L
。這表示我們不需要具體知道前面有多少元素,只需要知道最後一個元素是什麼。
_
在 TypeScript 中通常表示「不需要的型別」或「無關緊要的型別」,所以我們使用 ...infer _
來跳過前面的所有元素。解法2 (花式):
type Last<T extends any[]> = [never, ...T][T['length']]
細節分析:
型別操作 (Type Manipulation)
T
前面加上 never
,這樣可以在訪問 T['length']
時得到陣列的最後一個元素。T['length']
會返回陣列 T
的長度,而這個長度正好是原始陣列最後一個元素的索引。步驟細節:
T
是 [string, number, boolean]
,長度為 3。[never, ...T]
會生成一個新陣列 [never, string, number, boolean]
,長度變為 4。[never, string, number, boolean][3]
,即 T['length']
的位置,會得到原始 T
的最後一個元素 boolean
。never
的作用:
處理空陣列:假設 T
是一個空陣列 []
,T['length']
為 0。此時 [never, ...T]
變成 [never]
,而 [never][0]
會返回 never
。這是一個安全的回應,因為空陣列沒有最後一個元素,因此返回 never
是合理的。
防止索引越界:對於非空陣列,[never, ...T]
確保訪問 T['length']
的索引是有效的。例如,對於 T = [string, number]
,T['length']
是 2,而 [never, string, number][2]
正好返回 number
,也就是 T
的最後一個元素。如果沒有 never
,T[T['length']]
可能會導致越界訪問錯誤。
這樣,我們就能順利通過測試啦 🎉 😭 🎉
本次介紹了 Last of Array
的實作,下一關會挑戰 Pop
,期待再相見!