typescript 类型体操 之 116-medium-replace

249 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

前言

在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,在上一篇文章中,我们完成了中等的第十三题,今天来做中等的第十四题 116-medium-replace

下面这个是类型体操github仓库:

type-challenges/type-challenges: Collection of TypeScript type challenges with online judge (github.com)

116-medium-replace

image.png

import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Replace<'foobar', 'bar', 'foo'>, 'foofoo'>>,
  Expect<Equal<Replace<'foobarbar', 'bar', 'foo'>, 'foofoobar'>>,
  Expect<Equal<Replace<'foobarbar', '', 'foo'>, 'foobarbar'>>,
  Expect<Equal<Replace<'foobarbar', 'bar', ''>, 'foobar'>>,
  Expect<Equal<Replace<'foobarbar', 'bra', 'foo'>, 'foobarbar'>>,
  Expect<Equal<Replace<'', '', ''>, ''>>,
]

从README和测试用例中能够得出,我们需要实现一个工具函数 Replace 能够用来替换掉字符串中的某些字符。这个工具函数的作用和 JS 的 replace 方法很相似。

通过 JS 对比学习

在 JS 中,本身就存在字符串方法 replace 来提供字符串替换:

image.png

实现 Replace

首先还是通过模板字符串我们能够判断一个字符串中是否存在某一个其他字符

type REP1 = "asd" extends `${infer Before}${"s"}${infer After}`
  ? `${Before}${After}`
  : never;
// type REP1 = "ad"

比方说上面这个例子,我们就成功获取到字符串字面量 's' 两边的字符串字面量

那么同理,我们就能够借助这种方式,来判断一个字符串字面量是否含有另一个字符串字面量,有的话就进行替换,没有就还是返回它本身

type Replace<
  S extends string,
  From extends string,
  To extends string
> = S extends `${infer Before}${From}${infer After}`
  ? `${Before}${To}${After}`
  : S;

type REP3 = Replace<'foobar', 'bar', 'foo'>
// type REP3 = "foofoo"

但是在这个时候测试中还会存在报错,原因就是我们没有考虑到第二个字符是空的情况

type REP2 = Replace<'foobarbar', '', 'foo'>
// type REP2 = "ffoooobarbar"

那么就在前面的条件连中加入判断,如果第二个字符是空字符串,那么就返回第一个参数本身。

type Replace<
  S extends string,
  From extends string,
  To extends string
> = From extends ""
  ? S
  : S extends `${infer Before}${From}${infer After}`
  ? `${Before}${To}${After}`
  : S;

这样测试就能够全部通过了。

知识点

关于上述提到了部分的知识点:

  1. 模板字面量
  2. infer 关键字
  3. 条件链

今天的知识点都是之前有提到过了,在这里就不在做过多的描写,不懂得可以去看一下之前的文章或者相关题型。

总结

今天我们做完了中等的第十四题,题型和之前几天的都非常相似,也算是集中练习一下模板字面量这部分的知识点。