重复多个函数参数多个、函数、参数

2023-09-03 13:32:09 作者:帅届扛把子

在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[]);
excel中任意函数中多个参数如何统一书写

但我希望在不需要对象的情况下实现它

另一种可能是添加方法重载,但这会将参数数量限制为我提供的重载数量,并且仍允许传递奇数数量的参数而不会出现类型错误

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您可以在我的文章中找到一些解释和测试