typescript - 打字稿:更改函数参数类型
问题描述
我正在设计一个类似 Hystrix 的可靠性 API,并希望它能够像这样工作:
const target = request-promise;
const dispatcher = new Dispatcher(target)
.fallback(...)
.circuitBreaker()
.throttle()
.end();
// The new function has same signature as the target,
// except that first argument becomes an array.
// It finally calls:
// request-promise('http://a.com')
// or
// request-promise('http://b.com')
dispatcher(['http://a.com', 'http://b.com'])
.then(...);
现在我有问题定义类型以使其返回一个新函数,其第一个参数类型可以成为原始类型的数组。
它不起作用:
type TargetFn<T> = (...args: [T, ...any[]]) => Promise<any>;
type WrappedFn<F> = F extends TargetFn<infer T> ? TargetFn<T | T[]> : unknown;
class Dispatcher<F extends TargetFn> {
constructor(private targetFn: F) {}
end(): WrappedFn<T> {
// ...
}
}
function chain<T, F extends TargetFn<T>>(fn: F): Dispatcher<T, F> {
return new Dispatcher<T, F>(fn);
}
chain((url: string) => Promise.resolve(url)).end();
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
得到编译错误:
错误 TS2345:“(url:字符串)=> Promise”类型的参数不可分配给“TargetFn<{}>”类型的参数。
参数“url”和“args_0”的类型不兼容。
- 类型“{}”不可分配给类型“字符串”。
解决方案
编译器有时会在推断它们相关的类型参数时遇到问题。
在我看来,一种可行且实际上更简单的方法是使用条件类型来提取第一个参数类型:
type TargetFn = (...args: any[]) => Promise<any>;
type WrappedFn<F> = F extends (a: infer A1, ...args: infer U) => Promise<infer R> ? (a: A1|A1[], ...args: U) => Promise<R> : unknown;
class Dispatcher<F extends TargetFn> {
constructor(private targetFn: F) {}
end(): WrappedFn<F> {
return null as any;
}
}
function chain<F extends TargetFn>(fn: F): Dispatcher<F> {
return new Dispatcher<F>(fn);
}
const o = chain((url: string) => Promise.resolve(url)).end();
o("") // call it with a string
o(["", ""]) // or an array
请注意,更好的版本WrappedFn
实际上会返回一个具有多个重载的函数,而不是带有第一个参数的函数A1|A1[]
。每个重载都会返回R
或R[]
酌情返回:
type WrappedFn<F> = F extends (a: infer A1, ...args: infer U) => Promise<infer R> ? {
(a: A1, ...args: U): Promise<R>
(a: A1[], ...args: U): Promise<R[]>
}: unknown;
const o = chain((url: string) => Promise.resolve(url)).end();
o("") // call it with a string, returns Promise<string>
o(["", ""]) // or an array, returns Promise<string[]>
推荐阅读
- javascript - 无法获取查询字符串数据
- c# - 尝试从 ASP.NET CORE 中的 URL 读取 XML 时出错
- java - 如何在字符串java中附加升序数字
- tensorflow - 如何使用tensorflow xla aot模式搭建CNN模型?
- excel-formula - Excel - 将 6 个月添加到日期,然后四舍五入到最近的季度
- .htaccess - htaccess 重写规则子文件夹
- git - conan.io:在消费者的工作目录中克隆包存储库
- h2 - H2 更改约束名称的问题
- python - 如何在 TensorFlow v1.9 中下载 MNIST?
- android - 如何通过 onClick 开始运行 onLocationChanged 方法