type-challenges:ReplaceAll

101 阅读1分钟

ReplaceAll

问题描述

实现 ReplaceAll<S, From, To> 将一个字符串 S 中的所有子字符串 From 替换为 To

例如

type replaced = ReplaceAll<'t y p e s', ' ', ''> // 期望是 'types'
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'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<'', '', ''>, ''>>
]
​
// ============= Your Code Here =============
// 答案
type ReplaceAll<S extends string, From extends string, To extends string> =
  S extends `${infer L}${From extends ''
  ? never
  : From}${infer R}`
  ? `${L}${To}${ReplaceAll<R, From, To>}`
  : S

这道题泛型参数和上一题 Replace一样,接受三个参数:S(源字符串),From(要替换的子字符串)和To(用于替换的新子字符串)。类型操作符的目的是将字符串S中的所有From子字符串替换为To子字符串。不一样的是将 S 中的所有 From 替换为 To

这里应该知道基本逻辑没有变,同事观察发现,如果想要替换所有的 From 替换为 To,需要使用递归,比如 foobarfoobar 中的 ob 替换为 b 时,现在变成了 fobarfoobar ,但这个时候需要跳过第一个 ob了,这就要求我们肯定是从泛型 R入手修改,所以这里应该使用ReplaceAll<R, From, To> 将泛型 R作为第一个参数进行修改。

这里拓展一下,如果我们要实现将所有的 ob 都替换为 b呢,即第一次替换变为 fobarfoobar 时,仍然要替换第一个 obb ,这个时候应该操作呢?

// 答案
type ReplaceAll<S extends string, From extends string, To extends string> =
  S extends `${infer L}${From extends ''
  ? never
  : From}${infer R}`
  ? ReplaceAll<`${L}${To}${R}`, From, To>
  : S

只需要将第一次修改之后的字符串继续当成第一个参数传入即可。