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

如何从对象数组中推断类型并保存以供项目使用?

自动生成杂乱API返回值的TypeScript类型方案

方案一:自定义Node.js脚本生成类型

自己编写逻辑遍历API返回的运行时数据,分析每个属性的所有可能类型,生成对应的TypeScript类型字符串并写入文件。适合简单场景,完全可控。

示例代码:

const fs = require('fs');

// 替换为实际从API获取的数据
const apiData = [
  { title: "test", name: "Katy Smith" },
  { title: ["ACNM", "AAF3"], name: "Mary Williams" },
  { title: "test2", name: { firstName: "John", lastName: "Doe" } },
];

// 分析数组元素,生成联合类型
function generateTypeFromArray(array) {
  if (!array.length) return '{}';
  
  const propTypeSet = {};

  array.forEach(item => {
    Object.entries(item).forEach(([prop, value]) => {
      const type = getValueType(value);
      if (!propTypeSet[prop]) propTypeSet[prop] = new Set();
      propTypeSet[prop].add(type);
    });
  });

  const typeLines = Object.entries(propTypeSet).map(([prop, types]) => {
    const unionType = Array.from(types).join(' | ');
    return `  ${prop}: ${unionType};`;
  });

  return `{\n${typeLines.join('\n')}\n}`;
}

// 递归获取值的TS类型字符串
function getValueType(value) {
  if (Array.isArray(value)) {
    if (value.length === 0) return 'unknown[]';
    const elemType = getValueType(value[0]);
    return `${elemType}[]`;
  }
  if (typeof value === 'object' && value !== null) {
    const objTypeLines = Object.entries(value).map(([prop, val]) => {
      return `  ${prop}: ${getValueType(val)};`;
    });
    return `{\n${objTypeLines.join('\n')}\n}`;
  }
  // 基础类型映射
  const typeMap = {
    string: 'string',
    number: 'number',
    boolean: 'boolean',
    undefined: 'undefined',
    null: 'null'
  };
  return typeMap[typeof value] || 'unknown';
}

// 生成完整的TS类型导出代码
const typeCode = `export type ApiResponseItem = ${generateTypeFromArray(apiData)}`;
fs.writeFileSync('./api-types.ts', typeCode, 'utf8');

方案二:使用现成工具库(推荐)

利用成熟的工具库直接从JSON数据生成TypeScript类型,无需自己编写复杂的类型分析逻辑,处理嵌套、联合类型更准确。比如quicktype,支持命令行和代码调用两种方式。

代码调用示例:

  1. 安装依赖:
npm install quicktype-core
  1. 编写生成脚本:
const { quicktype } = require('quicktype-core');
const fs = require('fs');

async function generateApiTypes() {
  // 替换为实际API返回数据
  const apiData = [
    { title: "test", name: "Katy Smith" },
    { title: ["ACNM", "AAF3"], name: "Mary Williams" },
    { title: "test2", name: { firstName: "John", lastName: "Doe" } },
  ];

  // 调用quicktype生成TS类型
  const result = await quicktype({
    inputJson: JSON.stringify(apiData),
    lang: 'typescript',
    topLevelName: 'ApiResponseItem', // 生成的类型名称
  });

  // 写入类型文件
  fs.writeFileSync('./api-types.ts', result.lines.join('\n'), 'utf8');
}

generateApiTypes();

运行脚本后,会生成符合需求的类型定义,自动处理联合类型和嵌套对象。

方案三:利用TypeScript Compiler API

借助TypeScript本身的类型推断能力,先将API数据作为常量写入临时文件,再通过TS Compiler API提取推断后的类型,最终生成类型文件。适合深度依赖TS的项目,生成的类型完全符合TS的推断规则。

示例代码:

import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';

// 替换为实际API返回数据
const apiData = [
  { title: "test", name: "Katy Smith" },
  { title: ["ACNM", "AAF3"], name: "Mary Williams" },
  { title: "test2", name: { firstName: "John", lastName: "Doe" } },
];

// 创建临时TS文件,包含API数据常量和类型别名
const tempFilePath = path.join(__dirname, 'temp-api-data.ts');
const tempCode = `
const apiData = ${JSON.stringify(apiData)} as const;
export type ApiResponseItem = typeof apiData[number];
`;
fs.writeFileSync(tempFilePath, tempCode);

// 初始化TS编译程序
const program = ts.createProgram([tempFilePath], {
  strict: true,
  target: ts.ScriptTarget.ESNext,
});

// 遍历临时文件的AST,提取目标类型
const sourceFile = program.getSourceFile(tempFilePath)!;
ts.forEachChild(sourceFile, node => {
  if (ts.isTypeAliasDeclaration(node) && node.name.text === 'ApiResponseItem') {
    const typeText = node.type.getText(sourceFile);
    const finalTypeCode = `export type ApiResponseItem = ${typeText};`;
    fs.writeFileSync('./api-types.ts', finalTypeCode, 'utf8');
  }
});

// 删除临时文件
fs.unlinkSync(tempFilePath);

运行这个TS脚本(需要ts-node或编译后执行),会生成准确的联合类型定义。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:35:55