【发布时间】:2021-12-26 13:57:55
【问题描述】:
背景
我正在尝试使用带标签的元组元素将现有的重载函数替换为剩余参数。
原始代码
这是原始重载函数的简化版本:
function doSomething(arg1: string, arg2: number):void;
function doSomething(arg1: string, arg2: number, arg3: unknown[]):void;
function doSomething(arg1: string, arg2: number, arg3: boolean):void;
function doSomething(arg1: string, arg2: number, arg3: unknown[], arg4: boolean):void {
// ...implementation
}
所以第三个和第四个参数是可选的,但是当提供时,顺序可以是:
arg3: unknown[]
arg3: unknown[], arg4: boolean
arg3: boolean
尝试的解决方案
我决定首先创建带标签的元组元素,然后根据提供的类型变量类型将它们的类型设置为提供的类型或never。然后过滤该元组,删除任何 never 元素并返回结果。
type CalcAdditionArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> = [
myArg3: ThirdArgType extends [] ? never : ThirdArgType,
myArg4 : [FourthArgType] extends [boolean] ? FourthArgType extends true ? true : never : never
]
type GetAdditionalArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> =
FilterType<CalcAdditionArgs<ThirdArgType, FourthArgType>, never>
FilterType 是元组过滤实用程序的修改版本,可在此处找到 https://stackoverflow.com/a/64034671/1798234
type FilterType<T extends unknown[], U = undefined> =
(T extends [] ?
[] :
(T extends [infer H, ...infer R] ?
([H] extends [U] ?
FilterType<R, U> :
[H, ...FilterType<R, U>]) :
T
)
);
为了清楚起见,这是使用它们的函数
function execute<
ThirdArgType extends unknown[] = [],
FourthArgType extends boolean = false
>(
arg1: string,
arg2: number,
...args:GetAdditionalArgs<ThirdArgType, FourthArgType>
): void {
// do something here
}
问题
这是 2 种实用程序类型的输出:
type a = CalcAdditionArgs<[], false>; // [myArg3: never, myArg4: never]
type b = CalcAdditionArgs<[], true>; // [myArg3: [string, number], myArg4: never]
type c = CalcAdditionArgs<[string, number], false>; // [myArg3: [string, number], myArg4: never]
type d = CalcAdditionArgs<[string, number, Function], true>; // [myArg3: [string, number, Function], myArg4: true]
type e = GetAdditionalArgs<[], false>; // []
type f = GetAdditionalArgs<[], true>; // [true]
type g = GetAdditionalArgs<[string, number], false>; // [string: number]
type h = GetAdditionalArgs<[string, number, Function], true>; // [[string, number, Function], true]
如您所见,GetAdditionalArgs(或者更确切地说是FilterType)正在剥离元组元素标签。
问题
我无法理解如何(如果可能的话)在实用程序类型中创建并操作元组类型。即创建一个空元组,然后向其中添加所需的类型。因此,我的解决方案是预先创建填充的元组,然后删除元素。
- 有谁知道为什么元组元素标签被
FilterType剥离,有没有办法使用现有的解决方案来解决这个问题?
或者
- 是否有更好/更简单的解决方案来实现我正在寻找的结果?
解决方案
感谢 @captain-yossarian 的回复和 @ford04 (https://stackoverflow.com/a/64194372/1798234) 的 SO 回答,我能够重新考虑使用休息参数的解决方案方法:
type Append<E extends [unknown], A extends unknown[]> = [...A, ...E]
type GetMyArrayArg<T extends unknown[]> = [myArrayArg: T extends [] ? never : T]
type GetMyBooleanArg<T extends boolean> = [myBooleanArg : [T] extends [boolean] ? T extends true ? true : never : never]
type AddParameter<T extends [unknown], U extends unknown[] = []> =
T extends [] ?
U :
T extends [infer H] ?
[H] extends [never] ?
U :
Append<T, U> :
U
type GetAdditionalArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> =
AddParameter<
GetMyBooleanArg<FourthArgType>,
AddParameter<
GetMyArrayArg<ThirdArgType>>
>
type a = GetAdditionalArgs<[], false>; // []
type b = GetAdditionalArgs<[], true>; // [myBooleanArg: true]
type c = GetAdditionalArgs<[string, number], false>; // [myArrayArg: [string, number]]
type d = GetAdditionalArgs<[string, number, Function], true>; // [myArrayArg: [string, number, Function], myBooleanArg: true]
【问题讨论】:
-
能否请您将可重现的示例放入一段代码并评论您遇到的错误?我并不是说你的问题不清楚。只是会更容易挖掘它
-
完全忘记添加了,谢谢提醒 :)
标签: typescript tuples typescript-generics