Skip to content

Files

Latest commit

21ba4d8 · Sep 3, 2023

History

History
49 lines (40 loc) · 2.37 KB

MinusOne.md

File metadata and controls

49 lines (40 loc) · 2.37 KB
标题 标签
MinusOne(数字减 1(数字应是正整数)) extends,infer(继承,推断)

数字减 1(数字应是正整数)。

  • 创建一个 ParseInt 类型,类型参数 T 应该是字符串,使用 infer 关键字推断如果字符串属于数值字符串,则返回推断的数值,否则返回 never。
  • 创建一个 ReverseString 类型,该类型用于反转字符串,因此类型参数是一个字符串,同样可以使用 infer 关键字即可完成反转,无法反转则返回空字符串。
  • 创建一个 RemoveLeadingZeros 类型,该类型的作用就是移除前置 0,使用 infer 关键字来推断是否含有前置 0,有就移除,无则返回字符串。
  • 创建一个 InternalMinusOne 类型,该类型的作用就是计算减法,使用 infer 首先推断首位字符,如果是 0,则直接返回 9,否则返回从 9 到 8 的数字对应字符(创建了一个数字数组,通过将首位字符当做索引来取值)。
  • 最后是 MinusOne 类型的实现,首先使用模板字符串将数值参数转换成字符串,然后使用 ReverseString 将字符串反转,然后使用 InternalMinusOne 计算反转后的字符串,然后再使用 ReverseString 反转,然后使用 RemoveLeadingZeros 移除反转后字符串的前置 0,最后使用 ParseInt 将字符串转成数值。

代码如下:

type ParseInt<T extends string> = T extends `${infer D extends number}`
  ? D
  : never;
type ReverseString<S extends string> = S extends `${infer F}${infer R}`
  ? `${R}${F}`
  : '';
type RemoveLeadingZeros<S extends string> = S extends '0'
  ? S
  : S extends `${'0'}${infer R}`
  ? `${RemoveLeadingZeros<R>}`
  : S;
type InternalMinusOne<S extends string> =
  S extends `${infer D extends number}${infer R}`
    ? D extends 0
      ? `9${InternalMinusOne<R>}`
      : `${[9, 0, 1, 2, 3, 4, 5, 6, 7, 8][D]}${R}`
    : never;
type MinusOne<T extends number> = ParseInt<
  RemoveLeadingZeros<ReverseString<InternalMinusOne<ReverseString<`${T}`>>>>
>;

使用方式:

type Zero = MinusOne<1>; // 0
type FiftyFour = MinusOne<55>; // 54

应用场景

如下所示,鼠标悬浮到对应的类型变量可以查看类型。