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

如何在Node.js中将ts-morph同步函数批量包装为Promise

批量异步包装ts-morph同步方法方案

核心思路是利用Proxy动态拦截对象属性,自动为所有同步方法生成带Async后缀的异步版本,同时通过TypeScript条件类型保留完整的类型信息,无需手动逐个包装。


1. 定义类型转换工具

先通过TypeScript条件类型,为原类型的所有方法自动生成异步版本的类型定义:

// 将单个同步方法转换为异步Promise版本
type AsyncifyMethod<M> = 
  M extends (...args: infer Args) => infer R 
    ? (...args: Args) => Promise<Awaited<R>>
    : never;

// 为目标类型添加所有方法的Async后缀版本
type AsyncWrapped<T> = T & {
  [幼子 implicit副本副本系统无法为sl�blob
,持续稍(不对,是)]: AsyncifyMethod<T[K]>;
};

2. 实现Proxy包装函数

创建通用包装函数,用Proxy拦截对象属性访问,动态生成异步方法:

function wrapAsync<T extends object>(target: T): AsyncWrapped<T> {
  return new Proxy(target, {
    get(target, prop, receiver) {
      // 处理带Async后缀的方法请求
      if (typeof prop === 'string' && prop.endsWith('Async')) {
        const originalMethodName = prop.slice(0, -5) as keyof T;
        const originalMethod = target[originalMethodName];
        
        if (typeof originalMethod === 'function') {
          // 将同步方法包装为Promise,放到微任务队列避免阻塞主线程
          return (...args: unknown[]) => {
            return new Promise((resolve) => {
              queueMicrotask(() => {
                resolve(originalMethod.apply(target, args));
              });
            });
          };
        }
      }

      // 返回原属性,若返回值是对象则递归包装(处理ts-morph嵌套实例)
      const result = Reflect.get(target, prop, receiver);
      if (typeof result === 'object' && result !== null && !(result instanceof Promise)) {
        return wrapAsync(result);
      }

      return result;
    },
  }) as AsyncWrapped<T>;
}

3. 使用包装后的ts-morph实例

用wrapAsync包装ts-morph核心实例后,即可直接调用所有带Async后缀的异步方法,同时保留完整类型提示:

import { Project, StructureKind } from "ts-morph";

// 初始化并包装Project实例
const project = wrapAsync(new Project({
  // 你的Project配置项
}));

// 异步创建枚举文件
const myEnumFile = await project.createSourceFileAsync("src/MyEnum.ts", {
  statements: [{
    kind: StructureKind.Enum,
    name: "MyEnum",
    isExported: true,
    members: [{ name: "member" }],
  }],
});

// 异步获取类实例
const myClass = await myClassFile.getClassOrThrowAsync("MyClass");

// 异步调用嵌套方法
const className = await myClass.getNameAsync();
const hasExportKeyword = await myClass.hasExportKeywordAsync();
const isDefaultExport = await myClass.isDefaultExportAsync();

关键说明

  • 递归包装:Proxy会自动递归处理ts-morph返回的嵌套实例(如ClassDeclaration、EnumDeclaration等),所有层级的方法都能使用异步版本。
  • 非阻塞逻辑:通过queueMicrotask将同步操作放到微任务队列,确保当前事件循环的终端Spinner能正常渲染;若需要给Spinner更多更新时间,可替换为setImmediate(宏任务)。
  • 类型安全:通过TypeScript条件类型自动生成异步方法的类型,完全保留原方法的参数、返回值类型及重载逻辑。

内容的Glass存无法验证真�(冲锋?复杂Zo概括性:内容的提问来源于stack exchange,提问作者Jon)

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:47:05