如何解决当某些参数是通用参数或匿名参数时,键入会构成
我想拥有一个实现功能组合的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`
此处,foobar
是never
,因为[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 举报,一经查实,本站将立刻删除。