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

如何在构建后从第三方依赖提取类型并生成类型文件?

从构建生成的第三方依赖中提取类型的实现思路

下面是几种可行的实现方案,适配你需要从构建后生成的第三方依赖(如@prisma/client)中提取类型并纳入自身源码的需求:

1. TypeScript 声明文件生成 + 简单脚本转换

先通过tsc生成目标类型的声明文件,再用脚本提取并转换为普通TS接口:

  • 第一步:创建一个仅导出目标类型的入口文件,比如extract-types.ts:
    export { Customer } from '@prisma/client';
    
  • 第二步:运行tsc命令生成声明文件:
    tsc extract-types.ts --declaration --emitDeclarationOnly --outDir ./temp-types
    
    这会在temp-types目录下生成extract-types.d.ts,里面包含Customer的完整类型定义。
  • 第三步:写一个简单的Node脚本,读取extract-types.d.ts内容,去掉declare关键字,整理成标准的TS接口文件:
    const fs = require('fs');
    const content = fs.readFileSync('./temp-types/extract-types.d.ts', 'utf8');
    // 提取Customer接口部分并处理格式
    const customerInterface = content.match(/interface Customer {[\s\S]+?}/)?.[0];
    if (customerInterface) {
      fs.writeFileSync('./src/Customer.ts', `export ${customerInterface}\n`);
      // 清理临时文件
      fs.rmSync('./temp-types', { recursive: true });
    }
    
  • 第四步:将上述步骤整合到项目构建脚本中,确保在prisma generate之后执行。

2. 使用 ts-morph 操作 TypeScript AST

ts-morph是一个封装了TypeScript API的工具,可以更便捷地解析和生成TS代码:

  • 安装依赖:
    npm install ts-morph --save-dev
    
  • 编写提取脚本generate-types.ts:
    import { Project } from 'ts-morph';
    import fs from 'fs';
    
    async function extractCustomerType() {
      const project = new Project();
      // 加载Prisma生成的类型文件
      const prismaSourceFile = project.addSourceFileAtPath('node_modules/@prisma/client/index.d.ts');
      
      // 获取Customer接口
      const customerInterface = prismaSourceFile.getInterface('Customer');
      if (!customerInterface) {
        throw new Error('未找到Customer接口');
      }
    
      // 生成目标TS文件内容
      const interfaceContent = `export interface Customer {
    ${customerInterface.getProperties().map(prop => 
      `${prop.getName()}: ${prop.getType().getText()};`
    ).join('\n  ')}
    

}`;

// 写入文件
fs.writeFileSync('./src/Customer.ts', interfaceContent);
console.log('Customer.ts 生成成功');

}

extractCustomerType().catch(err => console.error(err));

- 在`prisma generate`完成后,执行`node generate-types.ts`即可生成目标文件。

## 3. 直接使用 TypeScript 官方 API
无需额外依赖,用TS官方API解析类型定义:
- 确保已安装`typescript`依赖:
```bash
npm install typescript --save-dev
  • 编写脚本extract-types.ts:
    import * as ts from 'typescript';
    import fs from 'fs';
    
    function extractCustomer() {
      const compilerOptions: ts.CompilerOptions = {
        target: ts.ScriptTarget.ESNext,
        module: ts.ModuleKind.CommonJS
      };
    
      // 创建TS程序,加载Prisma的类型文件
      const program = ts.createProgram(['node_modules/@prisma/client/index.d.ts'], compilerOptions);
      const typeChecker = program.getTypeChecker();
      const prismaFile = program.getSourceFile('node_modules/@prisma/client/index.d.ts');
      
      if (!prismaFile) throw new Error('未找到Prisma类型文件');
    
      // 查找Customer导出符号
      const prismaModuleSymbol = typeChecker.getSymbolAtLocation(prismaFile)!;
      const exports = typeChecker.getExportsOfModule(prismaModuleSymbol);
      const customerSymbol = exports.find(s => s.name === 'Customer');
      
      if (!customerSymbol) throw new Error('未找到Customer类型');
    
      // 提取属性和类型
      const customerType = typeChecker.getTypeOfSymbolAtLocation(customerSymbol, customerSymbol.declarations![0]);
      const properties = customerType.getProperties();
    
      // 生成接口代码
      let interfaceCode = 'export interface Customer {\n';
      properties.forEach(prop => {
        const propType = typeChecker.getTypeOfSymbolAtLocation(prop, prop.declarations![0]);
        interfaceCode += `  ${prop.getName()}: ${typeChecker.typeToString(propType)};\n`;
      });
      interfaceCode += '}\n';
    
      fs.writeFileSync('./src/Customer.ts', interfaceCode);
    }
    
    extractCustomer();
    
  • 同样在prisma generate后执行该脚本即可。

4. 自定义 Prisma 生成器

直接集成到Prisma的生成流程中,无需额外脚本步骤:

  • 编写自定义生成器prisma-custom-generator.ts:
    import { generatorHandler } from '@prisma/generator-helper';
    import fs from 'fs';
    import path from 'path';
    
    // 映射Prisma类型到TS类型
    function mapPrismaType(prismaType: string): string {
      const typeMap: Record<string, string> = {
        String: 'string',
        Int: 'number',
        Boolean: 'boolean',
        DateTime: 'Date',
        Float: 'number'
      };
      return typeMap[prismaType] || prismaType;
    }
    
    generatorHandler({
      onManifest() {
        return {
          defaultOutput: '../src/generated',
          prettyName: '自定义类型提取器'
        };
      },
      onGenerate(options) {
        // 从Prisma数据模型中找到Customer模型
        const customerModel = options.dmmf.datamodel.models.find(m => m.name === 'Customer');
        if (!customerModel) return;
    
        // 生成接口代码
        let interfaceCode = 'export interface Customer {\n';
        customerModel.fields.forEach(field => {
          const tsType = mapPrismaType(field.type);
          interfaceCode += `  ${field.name}: ${tsType}${field.isRequired ? '' : ' | null'};\n`;
        });
        interfaceCode += '}\n';
    
        // 写入文件
        const outputPath = path.join(options.generator.output!.value, 'Customer.ts');
        fs.mkdirSync(path.dirname(outputPath), { recursive: true });
        fs.writeFileSync(outputPath, interfaceCode);
      }
    });
    
  • 在schema.prisma中添加该生成器:
    generator customTypes {
      provider = "ts-node ./scripts/prisma-custom-generator.ts"
    }
    
  • 运行prisma generate时,会自动生成Customer.ts文件到指定目录。

内容的提问来源于stack exchange,提问作者TruMan1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:43:22