如何基于TypeScript Definitions自动生成对应Interface?
问题描述
现有以下TypeScript类型定义:
export enum Category { car = 'car', truck = 'truck', } export interface IProperty { propertyName: string, propertyLabel: string, propertyType: 'string' | 'number', } export interface CategoryDefinition { category: Category, label: string, properties: IProperty[] }
以及定义类:
export class Definitions { public static get car(): CategoryDefinition { return { category: Category.car, label: "Car", properties: [ { propertyName: 'weight', propertyLabel: 'Weight', propertyType: 'number' }, { propertyName: 'color', propertyLabel: 'Color', propertyType: 'string' } ], }; } public static get truck(): CategoryDefinition { return { category: Category.truck, label: "Truck", properties: [ { propertyName: 'payload', propertyLabel: 'Payload', propertyType: 'number' }, { propertyName: 'axles', propertyLabel: 'Axles', propertyType: 'number' } ], }; } }
需要基于上述定义自动生成对应接口,目标结果如下:
export interface Car { weight: number, color: string } export interface Truck{ payload: number, axles: number }
由于需要处理30-40个类似定义,手动编写接口易出错,希望仅通过一次属性定义就能生成对应接口。
解决方案
方法一:TypeScript编译时类型推导(无运行时开销)
核心是利用TypeScript的字面量类型捕获和映射类型,让编译器自动推导目标接口,无需手动编写重复代码。
步骤1:修改Definitions保留字面量类型
默认情况下TypeScript会拓宽IProperty的属性类型,需要用as const固定字面量信息:
export class Definitions { public static get car() { return { category: Category.car, label: "Car", properties: [ { propertyName: 'weight', propertyLabel: 'Weight', propertyType: 'number' }, { propertyName: 'color', propertyLabel: 'Color', propertyType: 'string' } ], } as const; } public static get truck() { return { category: Category.truck, label: "Truck", properties: [ { propertyName: 'payload', propertyLabel: 'Payload', propertyType: 'number' }, { propertyName: 'axles', propertyLabel: 'Axles', propertyType: 'number' } ], } as const; } }
步骤2:创建通用类型工具
编写类型工具从属性数组推导接口结构:
// 将propertyType映射为TS原生类型 type PropertyToType<T extends { propertyType: 'string' | 'number' }> = T['propertyType'] extends 'string' ? string : number; // 从属性数组生成接口类型 type CreateInterface<T extends readonly { propertyName: string; propertyType: 'string' | 'number' }[]> = { [K in T[number]['propertyName']]: PropertyToType<Extract<T[number], { propertyName: K }>> };
步骤3:自动生成目标类型
直接通过类型工具推导所需接口:
export type Car = CreateInterface<typeof Definitions.car.properties>; export type Truck = CreateInterface<typeof Definitions.truck.properties>;
此时Car和Truck类型完全符合需求,全程是编译时操作,不会产生运行时代码。
方法二:Node.js脚本生成物理接口文件
如果需要生成实际的.ts接口文件,可以编写脚本批量生成:
步骤1:编写生成脚本(generate-interfaces.ts)
import * as fs from 'fs'; import { Definitions } from './path-to-your-definitions-file'; // 遍历Definitions的静态属性 const categories = Object.keys(Definitions) as Array<keyof typeof Definitions>; let outputCode = ''; categories.forEach(category => { const def = Definitions[category]; // 首字母大写生成接口名 const interfaceName = category.charAt(0).toUpperCase() + category.slice(1); // 生成接口属性行 const propertyLines = def.properties.map(prop => { const tsType = prop.propertyType === 'string' ? 'string' : 'number'; return ` ${prop.propertyName}: ${tsType},`; }).join('\n'); // 拼接接口代码 outputCode += `export interface ${interfaceName} {\n${propertyLines}\n}\n\n`; }); // 写入文件 fs.writeFileSync('./generated-interfaces.ts', outputCode.trim());
步骤2:运行脚本
在package.json中添加执行脚本:
{ "scripts": { "generate-interfaces": "ts-node generate-interfaces.ts" } }
执行命令生成文件:
npm run generate-interfaces
脚本会自动生成包含所有目标接口的generated-interfaces.ts文件。
内容的提问来源于stack exchange,提问作者Hafnernuss
相关产品推荐
相关产品推荐

