如何将泛型函数参数设为只读并转为异步函数?含接口批量需求
解决方案
要实现将泛型函数的参数设为只读并转为异步函数,同时批量处理接口内的所有函数,需要通过保留泛型参数的高阶类型来解决,避免直接使用Parameters/ReturnType导致泛型丢失的问题。
1. 单个函数的转换
首先定义两个核心类型工具:
ReadonlyArg<T>:将单个参数转换为只读形式(数组转为readonly数组,对象转为Readonly对象,基本类型保持不变)MakeFunctionAsync<T>:保留原函数的泛型参数,将参数转为只读,返回值包装为Promise
// 处理单个参数的只读转换 type ReadonlyArg<T> = T extends Array<infer U> ? readonly U[] : Readonly<T>; // 转换函数为异步且参数只读,保留泛型参数 type MakeFunctionAsync<T> = T extends <...G>(...args: infer Args) => infer R ? <...G>(...args: { [K in keyof Args]: ReadonlyArg<Args[K]> }) => Promise<R> : never;
测试示例:
// 原泛型函数 declare function foo<T>(bar: T, baz: T[]): T; // 转换后的异步函数 type AsyncFoo = MakeFunctionAsync<typeof foo>; // 类型结果:<T>(bar: Readonly<T>, baz: readonly T[]) => Promise<T>
2. 批量转换接口内的函数
定义MakeInterfaceFunctionsAsync<T>,遍历接口的每个属性,对函数类型应用上述转换:
type MakeInterfaceFunctionsAsync<T> = { [K in keyof T]: T[K] extends Function ? MakeFunctionAsync<T[K]> : T[K]; };
测试示例:
// 原接口 interface Methods { foo<T>(bar: T, baz: T[]): T; bar(baz: string): void; } // 转换后的异步接口 type AsyncMethods = MakeInterfaceFunctionsAsync<Methods>; // 类型结果: // { // foo<T>(bar: Readonly<T>, baz: readonly T[]): Promise<T>; // bar(baz: Readonly<string>): Promise<void>; // }
关键说明
- 使用
<...G>剩余泛型参数捕获原函数的所有泛型参数,确保转换后不丢失泛型定义 ReadonlyArg<T>针对数组和对象做了针对性处理,贴合示例中的readonly T[]和Readonly<T>需求- 批量转换时通过索引签名遍历接口属性,仅对函数类型进行转换,非函数属性保持原样
内容的提问来源于stack exchange,提问作者Cmo Sekil
相关产品推荐
相关产品推荐

