微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当某些参数是通用参数或匿名参数时,键入会构成

如何解决当某些参数是通用参数或匿名参数时,键入会构成

我想拥有一个实现功能组合的compose功能。我希望compose的定义是类型安全的,允许根据需要提供任意数量的参数,并处理本身是通用或匿名的参数以正确键入。最后一个要求对我来说是一个绊脚石。

我目前的定义,使用Recursive Conditional Types(在Typescript 4.1 Release Candidate中找到):

type Compose<Fns extends any[]> =
    Fns extends [(...args: infer Args) => infer Return] ? (...args: Args) => Return :
    Fns extends [(...args: infer Args0) => infer Ret0,(arg: infer Arg1) => Ret1,...infer Rest] ? (
        [Ret0,Arg1] extends [Arg1,Ret0] ? Compose<[(...args: Args0) => Ret1,...Rest]> :
        never
    ) :
    never;

declare function compose<Fns extends ((...args: any[]) => any)[]>(
    ...fns: Fns
): Compose<Fns>;

当所有功能都具有固定的已定义类型时,此方法非常适用:

declare function foo(x1: string,x2: number): number;
declare function bar(y: number): boolean;
declare function baz(z: boolean): string;

const foobarbaz = compose(foo,bar,baz); // (x1: string,x2: number) => string

当传递给compose函数之一是通用的时,就会出现问题:

declare function foo(x: string): number;
declare function bar<T>(foo: T): string;

const foobar = compose(foo,bar); // typed as `never`

此处,foobarnever,因为[Arg1,Ret0] extends [Ret0,Arg1]的{​​{1}}签入失败。该检查失败是因为Compose的{​​{1}}参数(因此也将bar推断为T,并且Arg1确实没有扩展unkNown 。但是,当然[unkNown,number](和[number,unkNown])可能是 T在这种情况下Arg1会通过。在许多情况下,Typescript会自动推断出此类通用参数,但此处并非如此。

使用匿名函数可以看到相同的问题:

number

此处,[number,number] extends [number,number]是隐式declare function foo(x: string): number; const foobar = compose(foo,x => x.toLocaleString()); // typed as `(x: string) => any` ,而不是x的返回值所隐含的any

最终,这些问题并不出乎意料:一个函数的返回值的限制和下一个函数的参数来自number,直到foo的返回值才使用。到TS解决这个问题时,参数和通用参数已经被评估。

我已经尝试过重新定义内容,以便在Compose的参数中有一种实际意义,即必须关联函数,而不是仅仅允许compose,但到目前为止还没有实现。 Typescript继续推断compose((...args: any[]) => any)[],并且总体输入中断。

作为参考,这是尝试:

any

({unkNown是一种在没有第一个成员的情况下,对传递的数组类型进行求值的类型-这里,type Composable<Types extends any[]> = Tail<Types> extends infer Tail ? Tail extends any[] ? { [I in keyof Tail]: I extends keyof Types ? (arg: Types[I]) => Tail[I] : never; } : never : never; declare function compose<Fns extends Composable<T>,T extends any[]>(...fns: Fns): Compose<Fns>; 对应于Tail之后的下一个项目) / sup>

但这只是将Tail[I]用于Types[I],然后any[]变成了以前的T。所以没有帮助。

无需尝试使用条件类型,我们可以编写Composable<T>的非可变版本来解决这个问题(因为每个参数都是根据前一个参数定义的),但随后它们只能处理一些困难的情况,功能的编码数量。这很可能是我会采用的解决方案,但是我的目标是避免这种情况。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。