一个关于 TypeScript 联合类型拆解的问题?

在 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 类型联合分配时会拆分成 falsetrue 的问题:Playground(局限性;当类型本身为 falsetrue 时会转为 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在分配的时候会变成truefalse,不大好处理


_KeyCombos的解释:

  1. T extends any ? [T] .. 表示使用union的分配特性,变成[string] | [number] | [boolean]
  2. (_KeyCombos<Exclude<O, T>> extends infer U extends any[]

    1. 假设当前分配的Tstring,相当于传入的是number | boolean, extends infer U计算推断出来的U的类型为[number]|[boolean]|[number | boolean]
    2. extends any[]用来推断返回的U是数组,就可以通过U[number]拿到数组里面的union类型
    3. 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,这个就不大好处理,没啥思路


回答:

拆分成单个倒是可以,组合的话暂时还没想到
一个关于 TypeScript 联合类型拆解的问题?
主要就是利用TS在对泛型做extends会将联合类型拆分成单个进行判断


回答:

typescript">type Callable<Param extends unknown[] = any, Return = any> = (...args: Param) => Return

type DistributeParam<Param, Return> = Param extends unknown ? (x: Param) => Return : never

type Transform<T extends Callable<[any], any>> = DistributeParam<Parameters<T>[0], ReturnType<T>>

type Test1 = Transform<(value: string | number) => void>

Playground Link

用条件类型的分配律就能解决第一个问题。

更进一步的话,我的初步思路是,需要将 Union Type 转化成 Tuple ,再从 Tuple 转化回 Union Type ,但目前没有稳妥的 Union Type 转化成 Tuple 的方式。


回答:

type Combinations<T> =

T extends any ? (k: infer I) => void extends ((k: T) => void) ? I : never : never;

然后:

type Transform<T> = Combinations<T> extends infer U ? (value: Exclude<T, U>) => void : never;

用这个类型来转换你的函数类型:

type Fn = (value: string | number | boolean) => void;

type AfterFn = Transform<Fn>; // 你想要的类型

以上是 一个关于 TypeScript 联合类型拆解的问题? 的全部内容, 来源链接: utcz.com/p/934644.html

回到顶部