【发布时间】:2020-09-28 13:33:06
【问题描述】:
我有以下功能:
const fn = async (bool, num, str) => {
// ...
};
-
bool是一个布尔值, -
num是一个数字 -
str是一个可选字符串
我还有以下 HOF 允许在调用时填充最后一个 可选 参数,如果它没有被调用者传递:
const hof = (callback) => {
return async (...args) => {
if (args.length) {
const lastArg = args[args.length - 1];
if ("string" === typeof lastArg) {
return callback(...args);
}
}
const s = await findString();
return callback(...[...args].concat(s));
};
};
这允许写作:
const fn = hof(async (bool, num, str) => {
// str will be valued, either by the caller, or by the hof
});
我如何才能完全键入hof,知道它不知道回调的参数(即它们可能因一种用法而异)?使用 TypeScript 是否也能做到这一点?
我设法通过泛型处理返回的类型:
const hof = <R>(
callback: (...args: any) => Promise<R>
): (...args: any) => Promise<R> => {
return async (...args) => {
// ...
};
};
但是那些动态参数能不能打出来,这样在使用const fn = hof(async (bool, num, str) => { ... });时,fn就只能接受回调的参数了? fn 签名和回调签名之间的唯一区别是,fn 允许未定义的 str 最后一个参数,而回调是强制的。
不是编译,而是类似的东西:
const hof = <R>(
callback: (...args: ???, s: string) => Promise<R>
): (...args: ???, s?: string) => Promise<R> => {
return async (...args) => {
// ...
};
};
如果我遇到XY problem,实际用法是MySQL transaction management。这种模式允许我在没有连接通过时自动启动一个新事务,或者如果它已经启动了一个事务,则使用调用者的连接。这个实现正在讨论here,但简而言之,我的现实生活hof:
const transactional = (run) => async (...args) => {
if (args.length) {
const lastArg = args[args.length - 1];
if (lastArg && "PoolConnection" === lastArg.constructor.name) {
return run(...args);
}
}
return _transactional(async (connection) => run(...[...args].concat(connection)));
};
如果您正在考虑更好的方法,请大喊;)
【问题讨论】:
-
作为旁注
"String" === lastArg.constructor.name很可能是错误的。如果您正在检查字符串原语,则执行typeof lastArg === "string"就足够了。检查构造函数名称的唯一原因是检查字符串object。但是,为此 1. 您可以使用lastArg instanceof String2. 您很可能不应该使用字符串对象。 -
@VLAZ 是的,好点,我的简化示例不是很好。 IRL,我正在检查该参数是否是 PoolConnection 的实例,如上一节所示,但是mysql lib没有公开这种类型,所以我不得不改用构造函数名称,除非你在想有更好的方法吗?
-
嗯,可能值得为此单独提出一个问题。我肯定会尝试公开它,但是您可以使用
instanceof。 -
只是一个快速的问题,当您说 sql 事务时,是否可以进行多次调用,因为不幸的是节点是异步的,事务不会像您期望的那样序列化,尤其是使用相同的连接对象.
-
这似乎有点像逆向的部分应用;我们可以进一步抽象一下,让 HOF 接受一些函数,并返回一个不接受最后一个参数的函数?
标签: javascript typescript callback signature higher-order-functions