[英]Infer the type of a wrapper from wrapped function
目的是从包装的 function 推断包装器的类型,即从参数类型返回类型。
我无法通过infer
实现这一点:
function wrap<T extends ((...args: any[]) => any) & { flag?: string }>(wrapped: T extends infer R ? R : never): T {
let wrapper = function () {
// ...
return wrapped(...arguments);
} as T;
wrapper.flag = wrapped.flag;
return wrapper;
}
let wrapped = (a: number, b: number) => `${a}{b}`;
// wrapper is ((...args: any[]) => any) & { flag?: string }
// should be ((a: number, b: number) => string & { flag?: string }
let wrapper = wrap(wrapped);
// foo is any
// should be string
let foo = wrapper('invalid');
在这种情况下如何在不明确指定包装器类型的情况下做到这一点?
给定类型T extends infer R? R: never
T extends infer R? R: never
,编译器几乎肯定无法推断出任何对T
有用的东西(因为它倾向于推迟评估这种条件类型,直到它为时已晚而无法推断T
)。 由于该类型本质上等同于T
,因此我们将在下面使用T
。
我认为wrap()
签名和实现应该是这样的:
function wrap<T extends ((...args: any[]) => any)>(
wrapped: T & { flag?: string }): T & { flag?: string } {
let wrapper = function () {
// ...
return wrapped(...arguments);
} as T & { flag?: string };
wrapper.flag = wrapped.flag;
return wrapper;
}
也就是说,我们将使用泛型参数T
来表示 function 类型,并将{flag?: string}
保留为单独的非泛型 object 类型,与T
相交。 您需要执行此类操作的原因与可选属性的可分配性规则有关:
在 TypeScript 中,缺少属性的 object 类型被认为可分配给具有任何类型的可选属性的 object。 例如,类型{foo: string}
可分配给类型{foo: string, bar?: number}
。 如果您有一个泛型类型T extends {foo: string, bar?: number}
,则T
可能是{foo: string}
,完全缺少bar
属性。
在您的情况下,如果您有一个通用类型T extends ((...args: any[])=>any) & {flag?: string}
,并传入一个没有已知flag
属性的 function 作为推理站点T
,编译器将推断T
只是没有flag
属性的 function 类型。 然后 function output 也没有flag
属性,你很难过。
为了确保编译器将输入和 function 的 output 解释为具有可选flag
属性,我们需要在输入和 Z78E6221F6393D1456681DB398F 中显式包含它,并且不给编译器失去跟踪它的机会, .
好的; 希望有帮助; 祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.