gpt4 book ai didi

typescript :可变函数参数取决于前面的参数

转载 作者:行者123 更新时间:2023-12-04 02:28:40 25 4
gpt4 key购买 nike

这个问题肯定有人问过,我几乎可以肯定。然而:

  1. 我找不到任何这样的问题
  2. Typescript 在最近取得了重大飞跃,因此现有的答案可能已经过时。

我在代码中经常使用的是函数参数的扩展运算符,它允许我接收可变长度的参数数组。我现在要做的是为一个函数创建 TS 类型定义,其中 arg1 类型取决于 arg2 类型,而 arg2 取决于 arg3,依此类推。

在 lodash 中非常像这样 https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/common/util.d.ts#L209

 flow<R2, R3, R4, R5, R6, R7>(f2: (a: ReturnType<T>) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4, f5: (a: R4) => R5, f6: (a: R5) => R6, f7: (a: R6) => R7): Function<(...args: Parameters<T>) => R7>;

lodash 方法显然非常有限,而且(在本例中)最多只有 8 个参数。这很好,我可以接受,但是,在 2021 年有没有更好、更递归的方法?一种对(理论上)无限 个参数执行相同操作的方法?

请随时关闭问题并向我指出现有答案(如果存在并且是最新的)。

最佳答案

通过条件类型的推断,这是可能的(尽管有点难看):

// convenience alias
type Func = (...args: any[]) => any;

// check arguments in reverse
// since typescript doesn't like deconstructing arrays into init/last
type CheckArgsRev<T extends Func[]> =
// get first two elements
T extends [infer H1, infer H2, ...infer R]
// typescript loses typings on the inferred types
// so this gains them back
? H1 extends Func ? H2 extends Func ? R extends Func[]
// actual check
// ensures parameters of next argument extends return type of previous
// you can substitute this with whatever check you want to add
// just know that H1 is the current argument type and H2 is the previous
// also if you change this to work with non-functions then change Func to an appropriate type
// like unknown to work with all types
? Parameters<H1> extends [ReturnType<H2>]
// it was a match, recurse onto the tail
? [H1, ...CheckArgsRev<[H2, ...R]>]
: never // invalid type, become never for error
: never : never : never // should never happen
// base case, 0 or 1 elements should always pass
: T;

// reverse a tuple type
type Reverse<T extends unknown[]> =
T extends [infer H, ...infer R]
? [...Reverse<R>, H]
: [];

// check args not in reverse by reversing twice
type CheckArgs<T extends Func[]> = Reverse<CheckArgsRev<Reverse<T>>>;

// make sure the argument passes the check
function flow<T extends Func[]>(...args: T & CheckArgs<T>) {
console.log(args);
}

// this is invalid (since number cannot flow into a string)
flow((x: string) => parseInt(x, 10), (x: string) => x + "1");
// this is valid (number flows into number)
flow((x: string) => parseInt(x, 10), (x: number) => x + 1);

Playground link

关于 typescript :可变函数参数取决于前面的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65652538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com