TypeScript 模式匹配

2023 年 1 月 26 日 星期四(已编辑)
/ ,
523
这篇文章上次修改于 2023 年 5 月 11 日 星期四,可能部分内容已经不适用,如有疑问可询问作者。

TypeScript 模式匹配

最近尝试学习了下 TypeScript 的高级应用,正好接触到了模式匹配,写一篇文章来记录下所学内容。

介绍

在 TypeScript 中 extends、infer 关键字是相当重要的,extends 除了可以约束类型以外,还可以进行模式匹配,然后通过 infer 声明变量来进行值的存储,例如下方定义的 Promise 类型:

type Result = Promise<'suemor'>;

我们要实现一个类型,把 suemor提取出来,使 Result 的值为 suemor,我们可以这样写:

type GetResult<T> = T extends Promise<infer Value> ? Value : never;
image-20230126230306694

image-20230126230306694

函数

我们在函数中同样可以进行类型匹配,提取它的参数,返回值类型。例如下方提取函数的参数类型:

image-20230126230329512

image-20230126230329512
type GetResult<T extends Function> = T extends (...args:infer Args) => unknown ? Args : never

type Result = GetResult<(name: string, age: number) => string>;

通过 infer 将参数类型保存到变量 Args 里面。

数组类型

数组也同样适用类型匹配,例如我们想提取它第一个元素的类型:

image-20230126224340001

image-20230126224340001
type Result = GetResult<[1, 2, 3]>;

type GetResult<T extends unknown[]> = T extends [infer First, ...unknown[]]
  ? First
  : never;

利用 infer 获取第一个元素的类型,剩余的元素类型用存放在 ...unknown[]中。

字符串类型

字符串类型也可以进行模式匹配,把匹配的字符串,存放在 infer 的局部变量中,如下实现字符串替换:

image-20230126225708009

image-20230126225708009
type Result = GetResult<"suemor and mike", "suemor", "jack">;

type GetResult<
  Str extends string,
  From extends string,
  To extends string
> = Str extends `${infer Prefix}${From}${infer Suffix}`
  ? `${Prefix}${To}${Suffix}`
  : Str;

把要替换的值(From)前后的字符串都存放在 Prefix 和 Suffix 两个变量中,再把 From 换成目标值(To)即可。

还有个例子,判断字符串是否以某个前缀开头:

image-20230126225131765

image-20230126225131765
type Result = GetResult<"suemor and mike", "suemor">;

type GetResult<
  Str extends string,
  Prefix extends string
> = Str extends `${Prefix}${string}` ? true : false;

把 Prefix 放在字符串开头进行匹配即可。

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...