TS试炼-10

摘要:

包含:Combination key type(组合键类型)、Permutations of Tuple(元组全排列)

1、Combination key type(组合键类型)

Github练习

ts 复制代码
Combs<['cmd', 'ctrl', 'opt', 'fn']> // 'cmd ctrl' | 'cmd opt' | 'cmd fn' | 'ctrl opt' | 'ctrl fn' | 'opt fn'

实现

ts 复制代码
type Combs<T extends any[]> = T extends [infer F extends string, ...infer R extends string[]]
  ? `${F} ${R[number]}` | Combs<R>
  : never;

2、Permutations of Tuple(元组全排列)

Github练习

ts 复制代码
 PermutationsOfTuple<[1, number, unknown]>
  // 结果:
  // | [1, number, unknown]
  // | [1, unknown, number]
  // | [number, 1, unknown]
  // | [unknown, 1, number]
  // | [number, unknown, 1]
  // | [unknown, number ,1]

第一种方法(容易理解)

ts 复制代码
// 将元组的每一项再包一层
type WrapArray<T extends any[]> = T extends [infer S, ...infer O] ? [[S], ...WrapArray<O>] : [];
// 判断两个类型是否相同
type MyEqual<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
// 从元组中剔除指定类型
type MyExclued<T extends any[], U> = T extends [infer S, ...infer O]
  ? MyEqual<S, U> extends true
    ? MyExclued<O, U>
    : [S, ...MyExclued<O, U>]
  : [];
// 获取全排列
type MyPermutationsOfTuple<T extends any[], U = T[number]> = [U] extends [never]
  ? []
  : U extends U
    ? [U extends any[] ? U[0] : never, ...MyPermutationsOfTuple<MyExclued<T, U>>]
    : [];
type PermutationsOfTuple<
  T extends unknown[],
  U extends unknown[] = WrapArray<T>,
> = MyPermutationsOfTuple<U>;

解释:
简单排列原理相同,只是需要转换一下,因为此处元组直接取number并不是原始每一项的联合。

第二种方法

ts 复制代码
// 将类型插入到元组的每一项后面
type Insert<T extends unknown[], U> = T extends [infer F, ...infer L]
  ? [F, U, ...L] | [F, ...Insert<L, U>]
  : [U];

type PermutationsOfTuple<T extends unknown[], R extends unknown[] = []> = T extends [
  infer F,
  ...infer L,
]
  ? PermutationsOfTuple<L, Insert<R, F> | [F, ...R]>
  : R;

解释:
通过:Insert<R, F> | [F, ...R]得到所有结果,其中:
R表示已经处理的字符的所有排序可能,
Insert<R, F>表示当前项不再第一位的所有可能,
[F, ...R]表示当前项在第一位的所有可能

第三种方式

ts 复制代码
type PermutationsOfTuple<T extends unknown[], Prev extends unknown[] = []> = T extends [
  infer First,
  ...infer Rest,
]
  ?
      | [First, ...PermutationsOfTuple<[...Prev, ...Rest]>] // 当前项作为第一项与其他项全排列
      | (Rest extends [] ? never : PermutationsOfTuple<Rest, [...Prev, First]>) // 剩余参数继续处理,让每一项都能成为第一项
  : [];

解释:
假设元组只有一项:[any]

此时:只会走此:[First, ...PermutationsOfTuple<[...Prev, ...Rest]>],相当于:[any, ...PermutationsOfTuple<[]>]结果就是[any]

假设为两项:[unknown, any]

此时[First, ...PermutationsOfTuple<[...Prev, ...Rest]>],相当于:[unknown, ...PermutationsOfTuple<[any]>],根据第一步结果,此时结果为[unknown, any]

在看(Rest extends [] ? never : PermutationsOfTuple<Rest, [...Prev, First]>)。此时Rest[any],结果相当于PermutationsOfTuple<[any], [unknown]>),最终结果为[any, unknown]

将两个结果联合:[unknown, any] | [any, unknown]

假设为三项:[never, unknown, any]

此时[First, ...PermutationsOfTuple<[...Prev, ...Rest]>],相当于:[never, ...PermutationsOfTuple<[unknown, any]>],根据第二步结果,此时结果为[never, ...([unknown, any] | [any, unknown])],即:[never, unknown, any] | [never, any, unknown]

在看。此时Rest[unknown, any],结果相当于PermutationsOfTuple<[unknown, any], [never]>),即:[unknown, ...PermutationsOfTuple<[...[never], ...[any]]>] | [any, ...PermutationsOfTuple<[...[never, unknow], ...[]]>]

以此类推[First, ...PermutationsOfTuple<[...Prev, ...Rest]>]为第一项在第一位,剩余项的全排列
(Rest extends [] ? never : PermutationsOfTuple<Rest, [...Prev, First]>):其他项在第一位,其他参数的全排列

第四种方式

ts 复制代码
type PermutationsOfTuple<T extends any[], R extends 0[] = []> = T extends []
  ? []
  : R['length'] extends T['length']
    ? never
    : T extends [infer First, ...infer Rest]
      ? [First, ...PermutationsOfTuple<Rest>] | PermutationsOfTuple<[...Rest, First], [...R, 0]>
      : never;

解释:
同第三种:感觉稍微好理解点。

3、

Github练习

ts 复制代码

实现

ts 复制代码

4、

Github练习

ts 复制代码

实现

ts 复制代码

5、

Github练习

ts 复制代码

实现

ts 复制代码

6、

Github练习

ts 复制代码

实现

ts 复制代码

7、

Github练习

ts 复制代码

实现

ts 复制代码

8、

Github练习

ts 复制代码

实现

ts 复制代码

9、

Github练习

ts 复制代码

实现

ts 复制代码

10、

Github练习

ts 复制代码

实现

ts 复制代码

评论

0条评论

logo

暂无内容,去看看其他的吧~