iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
JavaScript

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

第28關:Length of String!TypeScript 司馬遷,字"子長":字串有多長?

  • 分享至 

  • xImage
  •  

第28關:Length of String

關卡簡介

Compute the length of a string literal, which behaves like String#length.

計算字串常值的長度,行為類似於 String#length

任務說明:

type L = LengthOfString<'test'> // 4

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

type cases = [
  Expect<Equal<LengthOfString<''>, 0>>,
  Expect<Equal<LengthOfString<'kumiko'>, 6>>,
  Expect<Equal<LengthOfString<'reina'>, 5>>,
  Expect<Equal<LengthOfString<'Sound! Euphonium'>, 16>>,
]

冒險指南:

從以下幾個方向來思考:

  • 遞迴解法 (Recursive Approach):透過遞迴,我們可以逐字元地處理字串,然後累計長度。想像成我們每次拆解字串的一個字元,剩下的部分繼續遞迴處理,直到字串被完全拆解,最終我們累加所有的字元數量。

  • 字串模板類型 (Template Literal Types):透過 TypeScript 的模板字串功能,我們可以使用字串模式匹配(pattern matching)來分割字串,然後逐步對每個字元進行遞迴處理。這樣可以將字串的一部分提取出來並進行處理,然後再處理剩餘部分。

  • 陣列和長度 (Array and Length):要計算字串的長度,我們可以使用陣列來記錄每次遞迴步驟中所累積的字元。當字串完全被處理後,陣列中存放的就是字元的數量,最後只需要取出這個陣列的長度來計算字串的總長度。

通關方式:

解法1:


type LengthOfString<
  S extends string,
  T extends string[] = []
> = S extends `${infer F}${infer R}`
  ? LengthOfString<R, [...T, F]>
  : T['length'];

細節分析:

  • 類型定義 (Type Definition):

    • LengthOfString<S extends string, T extends string[] = []> 定義了一個型別 LengthOfString,它接受一個字串 S 作為輸入,並且使用一個默認的空陣列 T 來累計字元的數量。
  • 模板字串和遞迴 (Template Literals and Recursion):

    • S extends ${infer F}${infer R}
      這裡使用了 TypeScript 的模板字串類型來將字串 S 拆解成兩部分:F 是字串的第一個字元,R 是剩餘的字串。每次遞迴都會將 F 添加到累計陣列 T 中,然後對剩餘的字串 R 進行下一步遞迴。

https://ithelp.ithome.com.tw/upload/images/20241013/20168789fAmlDluvDj.png

  • 累積結果 (Accumulate Result):
    - [...T, F]:
    每次遞迴時,我們將新的字元 F 添加到累積陣列 T 中,通過擴展運算符來構建一個新陣列,包含了所有已處理過的字元。

  • 基礎情況 (Base Case):

    • 當字串 S 被完全拆解為空字串(即不再符合模板字串的分割條件)時,遞迴停止,直接返回累積陣列 T 的長度 T['length'],這就是最終的字串長度。

解法2:

type StrToArray<S> = S extends `${infer x}${infer xs}` ? [1, ...StrToArray<xs>] : [];
type LengthOfString<S extends string> = StrToArray<S>['length'];

細節分析:

  • 字串轉換為陣列 (String to Array)

    • StrToArray<S> 將字串 S 逐步拆分為陣列。通過模板字串類型,S 被拆解為第一個字元 x 和剩餘的字串 xs。每次遞迴時,將數字 1(代表一個字元)加入陣列,並繼續處理剩餘的字串 xs
  • 基礎情況 (Base Case)

    • 當字串 S 被完全拆解(即 S 不再匹配模板字串類型),遞迴停止,並返回一個空陣列 []。這是遞迴的結束條件。
  • 計算長度 (Calculate Length)

    • LengthOfString<S extends string> 使用了 StrToArray<S>['length'] 來計算字串對應的陣列長度。由於每個遞迴步驟中都會將 1 添加到陣列中,因此陣列的長度就是字串的長度。

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

總結:

本次介紹了 Length of String 的實作,下一關會挑戰 Flatten,期待再相見!


上一篇
第27關:Permutation!TypeScript 黑板上排列組合:你捨得解開嗎?
下一篇
第29關:Flatten!TypeScript 軍中情人:你問我愛你有多深~陣列有幾層?
系列文
TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言