Implement
ReplaceAll<S, From, To>which replace the all the substringFromwithToin the given stringS
實作 ReplaceAll<S, From, To>,其功能是在給定的字串 S 中,將所有子字串 From 替換為 To。
type replaced = ReplaceAll<'t y p e s', ' ', ''> // expected to be 'types'
接下來,你的任務是讓下面的type cases測試通過:
type cases = [
Expect<Equal<ReplaceAll<'foobar', 'bar', 'foo'>, 'foofoo'>>,
Expect<Equal<ReplaceAll<'foobar', 'bag', 'foo'>, 'foobar'>>,
Expect<Equal<ReplaceAll<'foobarbar', 'bar', 'foo'>, 'foofoofoo'>>,
Expect<Equal<ReplaceAll<'t y p e s', ' ', ''>, 'types'>>,
Expect<Equal<ReplaceAll<'foobarbar', '', 'foo'>, 'foobarbar'>>,
Expect<Equal<ReplaceAll<'barfoo', 'bar', 'foo'>, 'foofoo'>>,
Expect<Equal<ReplaceAll<'foobarfoobar', 'ob', 'b'>, 'fobarfobar'>>,
Expect<Equal<ReplaceAll<'foboorfoboar', 'bo', 'b'>, 'foborfobar'>>,
Expect<Equal<ReplaceAll<'', '', ''>, ''>>,
]
從以下幾個方向來思考:
替換判斷 (Replacement Check): 首先確認 From 是否為空字串。如果是,則返回原字串 S,因為無法進行任何替換。
字串拆解 (String Decomposition): 利用 TypeScript 的模板字串語法 (Template literals),將字串 S 拆分為三個部分:F(替換前的部分)、From(要替換的部分)和 R(替換後的部分)。
執行替換 (Perform Replacement): 如果在 S 中找到 From,則將其替換為 To,並組合成新的字串。如果未找到,則返回原字串 S。
遞迴實現 (Recursive Implementation): 使用遞迴方式逐步掃描 S,每次找到匹配的 From 後進行替換,再對剩下的部分 R 重複相同的過程,直到掃描整個字串。
邊界情況考量 (Consider Edge Cases): 在實作過程中,確保考慮到如果 From 不存在於 S 中,結果應該保持不變。
解法:
type Replace<S extends string, From extends string, To extends string> = From extends ''
? S
: S extends `${infer F}${From}${infer R}`
? `${F}${To}${R}`
: S;
細節分析:
條件型別 (Conditional Type): ReplaceAll<S> 是一個條件型別,使用模板字面型別來分解字串 S。它檢查 From 是否為空字串,若是,則直接返回原字串 S。
字串結構檢查 (String Structure Check): 當 S 符合格式 ${infer F}${From}${infer R} 時,infer F 提取出 From 前的部分,而 infer R 則捕捉 From 後剩餘的所有字符。
遞迴替換 (Recursive Replacement): 當找到符合的 From 時,將其替換為 To,並對剩下的部分 R 遞迴地繼續替換。這樣能確保所有的 From 都被替換。
保持不變 (Maintain Originality): 如果 From 沒有出現在 S 中,則返回原字串 S,確保只有在實際找到匹配時才進行替換。這樣的設計使得其他部分保持不變,僅進行指定的替換操作。
這樣,我們就能順利通過測試啦 🎉 😭 🎉
本次介紹了 ReplaceAll 的實作,下一關會挑戰 Append Argument,期待再相見!