在 TypeScript 的世界里,自定義類型從字符串數組中顯現,就像隱藏的寶石。
TypeScript 是一個操縱現有數據和發展良好實踐的神奇工具。
今天,我們將探索如何以正確的方式從字符串數組中提取全名,以確保產生干凈的類型安全輸出。
那么,不多說了……讓我們直接開始吧。
首先讓我們通過檢查這段代碼來理解其中的問題:
const names = ["Daniel Craciun", "John Doe", "Harry Pigeon"]const findName = (surname: string) => { return names.find((name) => name.includes(surname))}// 我們可以傳入任何字符串,這是不理想的。console.log(findName("Craciun")) // 輸出:Daniel Craciunconsole.log(findName("Doee")) // 輸出:undefined
這段代碼使用一個名字數組來進行搜索。
函數 findName 接受一個字符串 surname 并返回關聯的全名。
問題出現在當你在 findName 函數中輸入 "Doee" 時。
這個不顯眼的拼寫錯誤導致輸出了 undefined,這可能會導致后續的錯誤,因為沒有任何東西阻止我們犯這種錯誤。
這就是 TypeScript 發揮作用的地方。
如果我們確保 findName 只接受字面上的姓氏,即 Craciun、Doe、Pigeon,那么當我們輸入像 "Doee" 這樣在名字數組中不存在的輸入時,編譯器應該會提出警告。
我們已經確定了 findName 的有效參數只能是所有現有的姓氏。
為了實現這一點,我們創建了一個名為 ExtractSurname 的泛型類型。
ExtractSurname 的代碼可能看起來有點復雜,但我們將一步步拆解它:
type ExtractSurname<T extends string> = T extends `${infer Firstname} ${infer Surname}` ? Surname : null
這里 ExtractSurname 接受一個泛型參數 T,它引用任何字面字符串,使用 extends 操作符。在 ExtractSurname<“Daniel”> 中,T 的值將等于 "Daniel"。
接下來我們應用 TypeScript 三元運算符,它類似于 JavaScript 三元運算符,但我們是在比較類型而不是實際數據。
我們知道我們的名字數組的格式是“<名> <姓>”,所以這里使用 infer 關鍵字從 T 中提取子類型。
在 ExtractSurname<“Daniel Craciun”> 中:
最后,如果輸入滿足我們的“<名> <姓>”格式,返回 Surname 作為類型,否則返回 null。
好的,我們的 ExtractSurname 類型準備好了。
現在我們需要一個 Surname 類型來表示 names 中所有的姓氏。
type ExtractSurname<T extends string> = T extends `${infer Firstname} ${infer Surname}` ? Surname : nullconst names = ["Daniel Craciun", "John Doe", "Harry Pigeon"] as consttype Surname = ExtractSurname<(typeof names)[number]>
names 滿足 ExtractSurname 的格式 “*<名> <姓>*”。
我們使用 as const 將 names 的類型從字符串縮小到字面字符串數組。
這意味著我們轉換 names 的類型從 string 到:readonly [“Daniel Craciun”, “John Doe”, “Harry Pigeon”]。
參數 (typeof names)[number] 代表 names 中每個索引元素的類型:“Daniel Craciun” | “John Doe” | “Harry Pigeon”
最終,這是 Surname 的結果類型:type Surname = “Craciun” | “Doe” | “Pigeon”
最后一步是用下面的新函數 findNameUsingSurname 更新我們之前定義的 findName 函數:
// 接收一個實際的 `Surname` 而不是一般的字符串。const findNameUsingSurname = (surname: Surname) => { // 注意:我們需要后綴運算符 "!" 來斷言 "find" 函數不返回未定義的值。 return names.find((name) => name.includes(surname))!}// 唯一可接受的輸入:"Craciun", "Doe", "Pigeon" = 最大類型安全const fullName = findNameUsingSurname("Craciun")// 輸出:"Daniel Craciun"console.log(fullName)
而這里是 TypeScript 編譯器如我們所期待的那樣施展它的魔法:
本文鏈接:http://www.tebozhan.com/showinfo-26-87964-0.html這個 TypeScript 技巧會讓你大吃一驚
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com