🤔️要求
实现一个可以将 union
转化为 tuple
的类型 UnionToTuple
。
由于 union
是一个无序结构, tuple
是一个有序结构。因此在这个挑战中, tuple
中的元素顺序可以以任何顺序返回。但不能为他们的联合类型。
UnionToTuple<1> // [1], and correct
UnionToTuple<'any' | 'a'> // ['any','a'], and correct
或者
UnionToTuple<'any' | 'a'> // ['a','any'], and correct
他不应该是所有正确类型的 union
类型
UnionToTuple<'any' | 'a'> // ['a','any'] | ['any','a'], which is incorrect
类型是可以省略的,例如。
Equal<UnionToTuple<any | 'a'>,UnionToTuple<any>> // will always be a true
Equal<UnionToTuple<unknown | 'a'>,UnionToTuple<unknown>> // will always be a true
Equal<UnionToTuple<never | 'a'>,UnionToTuple<'a'>> // will always be a true
Equal<UnionToTuple<'a' | 'a' | 'a'>, UnionToTuple<'a'>>// will always be a true
📖知识点
🔗知识链接
- UnionToIntersection
type UnionToIntersection = (T extends any ? (args: T) => any: never) extends (args: infer R) => any ? R : never;
以 UnionToIntersection<'a' | 'b' > 为例。
* T extends any 利用了 extends 的 [distribute](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types) 特性。 因为任何类型都 extends any, 转化为 `((args: 'a') => any | (args: 'b') => any) extends (args: infer R) => any ? : R : never;`
* [如果在 extends 中使用 infer。 对于给定的infer类型变量V,如果有候选类型是从协变的位置上推断出来的,那么V的类型是那些候选类型的联合。反之,如果有候选类型是从逆变的位置上推断出来的,那么V的类型是那些候选类型的交叉类型。否则V的类型是never。](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types)
* 根据上面这个原理, 因为 infer R 是在逆变的位置, 所以`infer R` 的值为候选类型的联合类型 `'a' & 'b'`
具体可以看我上次写的一篇文章 juejin.cn/post/697624…
-
如何判断一个类型是否为 Never ?
- 参考链接1: github.com/type-challe…
- 参考链接2: github.com/microsoft/T…
-
函数重载
-
获取重载类型的返回类型会获得最后一项的类型
type Override<T> = UnionToIntersection<(T extends any ? (arg: T) => T : never)>
type A = Override<'a' | 'b'> //(arg: 'a') => 'a' & (arg: 'b') => b
declare const fn : A ; // 定义一个类型为 A 的函数 fn
fn('a') // no error
fn('b') // no error
type R = ReturnType<A>; // 获得类型 A 的最后一项类型 'b'