在 TypeScript 中如何将 (value: string | number) => void 类型转换为 ((value: string) => void) | ((value: number) => void) 类型?
更近一步的话希望可以:
// 要实现的高级类型 type Transform<T> = .... // 原始类型 type Fn = (value: string | number | boolean) => void // 转换后类型 type AfterFn = | ((value: string | number) => void) | ((value: string | boolean) => void) | ((value: number | boolean) => void) | ((value: string) => void) | ((value: number) => void) | ((value: boolean) => void)
补充:其实真实的情况是原始函数类型会有 n 个参数 (value: string | number, foo: any, baz: any) => void,但只需要拆分第一个参数。
感谢 @kkopite 提供的思路,在大佬的基础上处理了 boolean 类型联合分配时会拆分成 false 和 true 的问题:Playground(局限性;当类型本身为 false 或 true 时会转为 boolean)
// 要实现的高级类型
type Transform<T extends (...args: any[]) => any> = 
  _ToFunc<_KeyCombos<Parameters<T>[0]>, ReturnType<T>>
type _KeyCombos<T, O = T> =
  T extends any
  ? [T] | (_KeyCombos<Exclude<O, T>> extends infer U extends any[]
    ? U extends U ? [T | U[number]] : never
    : never)
  : never
type _ToFunc<T extends Array<any>, R> = T extends any ? (val: T[0]) => R : never
type Fn = (value: string | number | boolean) => void
type a = Transform<Fn>
有个问题是boolean在分配的时候会变成true和false,不大好处理
_KeyCombos的解释:
- T extends any ? [T] ..表示使用union的分配特性,变成- [string] | [number] | [boolean]
- (_KeyCombos<Exclude<O, T>> extends infer U extends any[]:- 假设当前分配的T是string,相当于传入的是number | boolean,extends infer U计算推断出来的U的类型为[number]|[boolean]|[number | boolean]
- extends any[]用来推断返回的- U是数组,就可以通过- U[number]拿到数组里面的- union类型
- U extends U ? [T | U[number]]在此用到union的分配特性,这里T是- string的话,而- U是- [number]|[boolean]|[number | boolean],一次就得到了- [number | string]|[boolean | string]|[number | boolean | string]
 
- 假设当前分配的
ps: 实际上是没有boolean这个类型的,分配的时候会变成
false|true,这个就不大好处理,没啥思路
 
    		 
             
		