如何为带登录状态校验的包装函数设置正确的TypeScript类型
解决TypeScript函数包装器的入参类型不兼容问题
问题背景
需要实现一个函数包装器wrap:接收请求函数B,完成登录状态校验后返回函数C。要求返回的函数C与原函数B的入参完全一致(包括必填参数的约束),且返回值为B的返回值或null。
当前实现代码:
const wrap = <Req, Res>(B: (req?: Req, options?: any) => Promise<Res>) => { return async (req?: Req, options?: any) => { const loginStatus = await loginStatusPromise; if (loginStatus) { return null; } return B(req, options); }; };
调用时传入含必填参数currency的函数B:
const funcD = wrap<string, obj>(async (currency: string) => requestfunc({platform: "WEB", currency}));
触发TypeScript错误:
Types of parameters 'currency' and 'req' are incompatible. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ts(2345)
错误原因
原实现中泛型Req被定义为可选参数,导致包装后的函数参数也变成可选类型,但传入的原函数B的currency是必填参数,两者类型不匹配。
修正方案
通过泛型捕获原函数的完整签名,确保包装后的函数参数与原函数完全一致:
// 泛型F捕获原函数的完整类型:参数列表 + 返回值类型 const wrap = <F extends (...args: any[]) => Promise<any>>(B: F) => { return async (...args: Parameters<F>): Promise<ReturnType<F> | null> => { const loginStatus = await loginStatusPromise; // 登录状态校验失败时返回null if (loginStatus) { return null; } // 校验通过,调用原函数并返回结果 return B(...args); }; };
代码说明
- 泛型
F约束为返回Promise的函数类型,完整捕获原函数的参数和返回值信息 - 返回的函数使用
Parameters<F>获取原函数的参数列表,保证必填参数依然保持必填,入参结构完全一致 - 返回值类型定义为
Promise<ReturnType<F> | null>,满足“登录失败返回null,成功返回原函数结果”的需求 - 内部调用原函数时使用扩展运算符
...args传递所有参数,避免参数遗漏或类型不匹配
验证调用
修正后再调用wrap,原函数的必填参数约束会被正确保留,不会触发类型错误:
const funcD = wrap(async (currency: string) => requestfunc({platform: "WEB", currency})); // 调用funcD时必须传入currency参数,符合原函数的约束 funcD("USD"); // 正确 funcD(); // 触发TS错误:缺少必填参数
内容的提问来源于stack exchange,提问作者andy
相关产品推荐
相关产品推荐

