You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将泛型函数参数设为只读并转为异步函数?含接口批量需求

解决方案

要实现将泛型函数的参数设为只读并转为异步函数,同时批量处理接口内的所有函数,需要通过保留泛型参数的高阶类型来解决,避免直接使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:15:17