TypeScript接口映射时如何保留函数重载?
如何为带函数重载的接口生成异步版本?
假设有一个包含函数重载的接口:
interface Api { parseNumber(input: string, useBigInt: true): bigint parseNumber(input: string, useBigInt: false): number }
需要生成一个新接口,其中每个函数都变为异步版本,返回值包裹在Promise中,目标接口如下:
{ parseNumber(input: string, useBigInt: true): Promise<bigint> parseNumber(input: string, useBigInt: false): Promise<number> }
已尝试方案的问题
直接通过映射类型处理时,会丢失除最后一个以外的所有函数重载:
type TMethodNames = keyof Api; // 正确:`parseNumber` type TMethodImplementations = Api[keyof Api]; // 正确:包含两个签名 type TMethodReturns = ReturnType<TMethodImplementations> // 错误:仅得到`number`而非`number | bigint` type AsyncApi = { [TMethodName in keyof Api]: (...args: Parameters<Api[TMethodName]>) => Promise<ReturnType<Api[TMethodName]>> }; const asyncApi = null as unknown as AsyncApi; asyncApi.parseNumber('123', false); // 正确:返回类型为`Promise<number>` asyncApi.parseNumber('123', true); // 错误:该签名完全丢失
解决方案
通过定义一个工具类型,将每个函数重载单独转换为异步版本,再利用TypeScript对交集类型的处理保留所有重载:
// 工具类型:将单个函数转换为异步版本 type Asyncify<T> = T extends (...args: infer Args) => infer Return ? (...args: Args) => Promise<Return> : never; // 生成异步版本接口 type AsyncApi = { [K in keyof Api]: Asyncify<Api[K]>; }; // 测试验证 const asyncApi = null as unknown as AsyncApi; asyncApi.parseNumber('123', false); // 返回 Promise<number> asyncApi.parseNumber('123', true); // 返回 Promise<bigint>
原理:TypeScript中,函数重载会被表示为多个函数类型的交集。Asyncify工具类型会对交集中的每个函数类型单独处理,将其转换为异步版本,最终结果依然是多个异步函数的交集,从而完整保留所有重载签名。
内容的提问来源于stack exchange,提问作者steveluscher
相关产品推荐
相关产品推荐

