标签:Typescript 子句 never extends 体操 Permutation 类型 type
题目
中文
实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。
type perm = Permutation<'A' | 'B' | 'C'>; // ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']
English
Implement permutation type that transforms union types into the array that includes permutations of unions.
type perm = Permutation<'A' | 'B' | 'C'>; // ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']
答案
type Permutation<T, K = T> = [T] extends [never]
? []
: K extends K
? [K, ...Permutation<Exclude<T, K>>]
: never;
解析
这个题目挺有意思的,要你把联合类型转成一个由数组构成的联合类型,要求输出的数组联合类型是输入的联合类型的所有可能的排列组合,看示例比较容易理解
type Perm = Permutation<'A' | 'B' | 'C'>;
// Perm的类型应该是 -> ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']
答案中的K extends K
的是遍历联合类型
type TraversalUnion<T extends string> = T extends T ? `Traversaled ${T extends string ? T : never}` : never;
type T = TraversalUnion<'a' | 'b'>
// T的类型 -> "Traversaled a" | "Traversaled b"
理解了这点,就可以去递归了
K extends K
? [K, ...Permutation<Exclude<T, K>>]
: never
[K, ...Permutation<Exclude<T, K>>]
这个子句中,第一个元素是通过K extends K
遍历出来的一个联合类型, 第二个元素递归调用了Permutation
,且使用了一个数组展开运算符(...
), 它的参数Exclude<T, K>
, 在Permutation
的定义中泛型参数T
是等于K
的,子句中的K
的遍历出来的一个子项,T
是完整的联合类型,很巧妙的就递归下去了;
最后回到第一个子句
[T] extends [never]
? []
...
这个子句其实就是递归的终止条件,上面递归的子句中使用了Exclude
, 所以递归到最后传给Permutation
的就是个never
(Exclude两个泛型参数相同时,返回的就是never)
标签:Typescript,子句,never,extends,体操,Permutation,类型,type 来源: https://www.cnblogs.com/laggage/p/type-challenge-permutation.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。