typescript - 键入通用包装函数以充当记录器?
问题描述
我有一个包装任何函数的通用 JS 函数,这样当调用包装器时,它将执行包装的函数,记录事件(函数的输入和输出)然后返回输出,从而导致“透明“记录。我的问题是,尝试将此函数移动到 TS 并保存包装函数和输出的类型信息被证明有点复杂。
这是我目前所在的位置:
const syncLogger = <T>(f: T) => (...args: unknown[]): ReturnType<T> => {
let value;
try {
value = f(...args);
functionLogger('info', f, value, ...args); // actual logging
} catch (error) {
functionLogger('error', f, error.message, ...args); //actual logging
throw error;
}
return value;
};
这就是它应该如何使用:
const myLoggedFunction = syncLogger(originalFunction);
主要问题在于args
,我曾经用作函数输入的 n 个参数的列表:我认为无法让 TS 知道这些参数与要包装的原始函数的参数完全对应。
解决方案
我会在参数元组和函数的返回类型中都使用syncLogger
泛型,如下所示:A
R
const syncLogger = <A extends any[], R>(f: (...a: A) => R) => (
...args: A
): R => {
let value;
try {
value = f(...args);
functionLogger("info", f, value, ...args); // actual logging
} catch (error) {
functionLogger("error", f, error.message, ...args); //actual logging
throw error;
}
return value;
};
这应该可以按您的预期工作:
function originalFunction(x: string, y: number): boolean {
return (x <= y.toFixed())
}
const myLoggedFunction = syncLogger(originalFunction); // okay
// const myLoggedFunction: (x: string, y: number) => boolean
const bool = myLoggedFunction("121", 123); // info, originalFunction, true, "121", 123
console.log(bool) // true
事实上,在许多情况下,即使原始函数本身是通用的,这也可以工作,因为 TypeScript 3.4 中添加了对推断高阶函数类型的支持:
const loggingItself = syncLogger(syncLogger);
// TS3.3-:
// const loggingItself: (...args: any[]) => (...args: any[]) => {}
// TS3.4+:
// const loggingItself: <A extends any[], R>(f: (...a: A) => R) => (...args: A) => R
无论如何,希望这会有所帮助。祝你好运!
推荐阅读
- node.js - 如何使用 NodeJs (typescript) 和 Sequelize 5 (PostgreSQL) 进行单元测试?
- java - 过滤出 Java 8 流过滤器表达式中的空值,因此不会引发异常
- django - 有没有一种方法可以在 Django 中创建记录时自动创建页面(和 slug)
- python - 在 Pillow 中使用 ImageTk 打开图像会导致 AttributeError 和 RuntimeError?
- python - Keras Tokenizer 序列到文本更改词序
- c# - MongoDB C# Linq 动态查询可空日期
- java - 如何模糊渐变背景?
- django - 使用 JSONFields 与纯 SQL 方法 Django Postgres 的效率
- python - 用 API 数据制作字典
- ios - macOS Simulator 部署目标设置为 13.5,但此平台支持的部署目标版本范围为 13.1 到 13.4.999