【Typescript 系列】类型体操之中等篇题型(第二十一节)解读

164 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

1. 引言

接着上一节中,接下来我们继续Ts中等篇的题型练习 https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!

2. 题型

  1. Combination:给定一个字符串数组,进行排列和组合。它对于像video controlsList这样的道具类型也很有用

type Keys = Combination<['foo', 'bar', 'baz']> // expected to be `"foo" | "bar" | "baz" | "foo bar" | "foo bar baz" | "foo baz" | "foo baz bar" | "bar foo" | "bar foo baz" | "bar baz" | "bar baz foo" | "baz foo" | "baz foo bar" | "baz bar" | "baz bar foo"`

思路:    首先该题考验我们的是数组元素的多种不同排列组合方式;由于传入的参数是一个数组我们就可以采用${I} ${Combination<[], Exclude<A, I>>} 的方式递归操作数组剩余的内容,在此之前我们要使用infer 关键字来退下I类型是否为数组类型,如果是的会直接回抛,避免U和A的类型不对导致的报错问题,在这个解决的思路中我们巧妙的通过I | 来返回所有的联合类型并且配合状态检测,规避了很多类型不匹配的报错问题,该题结束,完成; 解答:

type Combination<T extends string[], A = T[number], U = A> = 
  U extends infer I extends string
    ? I | `${I} ${Combination<[], Exclude<A, I>>}`
    :never
type Demo = Combination<['foo', 'bar', 'baz']// type Demo = 'foo' | 'bar' | 'baz' | 'foo bar' | 'foo bar baz' | 'foo baz' | 'foo baz bar' | 'bar foo' | 'bar foo baz' | 'bar baz' | 'bar baz foo' | 'baz foo' | 'baz foo bar' | 'baz bar' | 'baz bar foo'
  1. Subsequence:给定一个唯一元素数组,返回所有可能的子序列。

子序列是可以从数组派生的序列,只需删除一些元素或不删除元素,而不改变其余元素的顺序。

type A = Subsequence<[1, 2]> // [] | [1] | [2] | [1, 2]

思路:    首先该题考验的还是数组内部元素的所有组合方案,直接递归就好了并且我们在采用 | 连接,这样每次递归都会生成其中一项,这样就可以获得一个多种组合类型值的联合类型,通过每次递归执行并且每次都抽取其中一项后合并值操作,完成。 解答:

type Subsequence<T extends any[]> = 
  T extends [infer F, ...infer Rest]
    ? [F, ...Subsequence<Rest>] | Subsequence<Rest>
    : T
    
type Demo = Subsequence<[1, 2]> // type Demo = [] | [1] | [2] | [1, 2]
type Demo2 = Subsequence<[1, 2, 3]> // type Demo2 = [] | [1] | [2] | [1, 2] | [3] | [1, 3] | [2, 3] | [1, 2, 3]