在TypeScrip中是否有一种方法可以动态键入一个函数,该函数默认接受2个参数,但应该能够正确地处理这些参数。
// should be allowed
myFunction(paramA, paramB)
myFunction(paramA, paramB, paramA1, paramB1)
myFunction(paramA, paramB, paramA1, paramB1, paramA2, paramB2)
...
// should produce an error
myFunction(paramA, paramB, paramA1)
当然可以将参数打包到对象中并接受此对象的可迭代
interface Param { a: string; b: number; };
function myFunction(...params: Param[]);
但我希望在不需要对象的情况下实现它
另一种可能是添加方法重载,但这会将参数数量限制为我提供的重载数量,并且仍允许传递奇数数量的参数而不会出现类型错误
function myFunction(paramA: string, paramB: number);
function myFunction(paramA: string, paramB: number, paramA1: string, paramB1: number);
function myFunction(paramA: string, paramB: number, paramA1?: string, paramB1?: number);
是否有一些技巧可以优雅地允许通缉行为?
我相信这个问题与this有关。
我的解决方案仅适用于TS >=4.4
事实上,我们需要允许偶数个参数。这是最复杂的部分。
让我们定义允许的元组项目:
type Elem = number | string | boolean;
type Tuple = [Elem, Elem]
接下来,我们需要为一个长度为无穷大且为偶数的元组建模。
虽然我们可以对递归对象类型建模,但似乎不可能(或者我只是不知道如何)对长度为无穷大的元组进行建模。因为史密斯无限可能有偶数长度吗?
我甚至没有足够的数学背景来理解它。
我决定将偶数长度的元组建模为尽可能长。
考虑这个例子:
type Elem = number | string | boolean;
type Tuple = [Elem, Elem]
/**
* It is not allowed to increase this number, at least in TS.4.4
*/
type MAXIMUM_ALLOWED_BOUNDARY = 110
type Mapped<
Arr extends Array<unknown>,
Result extends Array<unknown> = [],
Original extends any[] = [],
Count extends ReadonlyArray<number> = []
> =
/**
* If Length reached the MAXIMUM - return Result
*/
(Count['length'] extends MAXIMUM_ALLOWED_BOUNDARY
? Result
/**
* If we passed an empty Arr - return empty tuple
*/
: (Arr extends []
? []
/**
* If Arr has only one element - infer it
*/
: (Arr extends [infer H]
/**
* and Return Result concatenated with infered element and recursive call
*/
? [...Result, H, ...([] | Mapped<Original, [], [], [...Count, 1]>)]
/**
* If Arr has more than one element
*/
: (Arr extends [infer Head, ...infer Tail]
/**
* Call Mapped recursively with appropriate parameters
*/
? Mapped<[...Tail], [...Result, Head], Arr, [...Count, 1]>
: Readonly<Result>
)
)
)
)
// [Elem, Elem] | [Elem, Elem, Elem, Elem] | [Elem, Elem, Elem, Elem, Elem, Elem] | [Elem, ... 6 more ..., Elem] | ... 50 more ... | [...]
type CaseCallParams = Mapped<Tuple>
function myFunction<Fst, Scd>(...params: Mapped<[Fst, Scd]>) {
}
myFunction(1, true) // ok
myFunction(1, true, 42, false) // ok
myFunction(1, 1, 2, 2) // ok
myFunction(1, 1, 2, 2, 3, 3) // ok
myFunction(1, true, 1, 1) // error
myFunction(1) // error
myFunction(1, 1, 2) // error
Playground
我希望110个元素(允许的最大参数数)足以满足您的要求
Here您可以在我的文章中找到一些解释和测试