[TypeScript] Type Challenges #119 - ReplaceAll

39 阅读1分钟

题目描述

实现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<T extends string, From extends string, To extends string> =
  From extends ''
      ? T
      : T extends `${infer L}${From}${infer R}`
          ? `${L}${To}${ReplaceAll<R, From, To>}`
          : T

类型约束

使用T extends string对类型T进行约束,确保T是一个字符串类型。同样,对FromTo也进行相同的约束,确保它们都是字符串类型

条件类型

type ReplaceAll<T extends string, From extends string, To extends string> =
  From extends ''
      ? T
      : T extends `${infer L}${From}${infer R}`
          ? `${L}${To}${ReplaceAll<R, From, To>}`
          : T
  • From extends '' ? T : ...
    • 如果From是空字符串,则直接返回T
  • T extends ${infer L}${From}${infer R} ? ${L}${To}${ReplaceAll<R, From, To>} : T
    • infer L用于推断出TFrom之前的部分
    • infer R用于推断出TFrom之后的部分
    • 如果T中包含From,则将From替换为To,并拼接L和递归调用ReplaceAll替换R
    • 如果T不包含From,则返回T本身