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

求助:如何利用TypeScript编译器API实现类型推断函数inferType?

使用TypeScript Compiler API实现类型推断函数

当然有可行的实现方法!咱们可以借助TypeScript Compiler API的类型检查能力来完成这个需求。下面是具体的实现思路和代码示例:

核心思路

  • 先创建一个TypeScript程序实例,用来解析和检查包含目标变量的临时代码
  • 定位到目标变量/函数对应的语法节点,获取它的符号(Symbol)和类型(Type)
  • 利用TypeScript内置的类型格式化工具,将类型对象转换为字符串形式

完整代码实现

import * as ts from 'typescript';

function inferType(target: unknown): string {
  // 处理函数的特殊情况:直接传入函数的话,JSON.stringify会丢失函数体,所以单独处理
  let code: string;
  if (typeof target === 'function') {
    // 提取函数的源码(注意:这个方式在常规开发场景可用,压缩后的代码可能受限)
    code = `const target = ${target.toString()};`;
  } else {
    // 普通变量用JSON.stringify嵌入到临时代码中
    code = `const target = ${JSON.stringify(target)};`;
  }

  // 创建临时源文件
  const sourceFile = ts.createSourceFile(
    'temp.ts',
    code,
    ts.ScriptTarget.Latest,
    true
  );

  // 创建TypeScript程序实例,启用严格模式确保类型推断准确
  const program = ts.createProgram({
    rootNames: ['temp.ts'],
    options: { strict: true }
  });
  const checker = program.getTypeChecker();

  // 找到目标变量的声明节点
  const targetDecl = sourceFile.statements.find(
    ts.isVariableStatement
  )?.declarations[0];
  if (!targetDecl) throw new Error('无法定位目标变量的声明');

  // 获取变量对应的符号和类型
  const symbol = checker.getSymbolAtLocation(targetDecl.name);
  if (!symbol) throw new Error('无法获取目标变量的类型符号');
  const type = checker.getTypeOfSymbolAtLocation(symbol, targetDecl.name);

  // 将类型转换为字符串,去掉参数名以匹配示例格式
  return checker.typeToString(
    type,
    undefined,
    ts.TypeFormatFlags.NoParameterNames
  );
}

// 测试示例
let bar = [1, 2, 3];
let bar2 = 5;
function foo(a: number[], b: number) { return a[0] + b; }

console.log(inferType(bar)); // 输出 "number[]"
console.log(inferType(bar2)); // 输出 "number"
console.log(inferType(foo)); // 输出 "(number[], number) => number"

关键细节说明

  • 临时源文件的作用:TypeScript Compiler API是基于源码进行类型分析的,所以我们需要把目标变量/函数嵌入到一段临时代码中,让编译器能正确解析它的上下文和类型
  • 函数的特殊处理:普通变量可以用JSON.stringify序列化,但函数不行,所以我们直接用toString()提取函数的源码(常规开发场景足够用,压缩混淆后的代码可能失效)
  • 类型格式化选项:ts.TypeFormatFlags.NoParameterNames这个选项可以让类型字符串去掉参数名,正好匹配你示例中(number[], number) => number的格式;如果需要保留参数名,去掉这个选项即可
  • 类型检查器(TypeChecker):这是整个实现的核心,它提供了获取类型、解析符号、格式化类型等一系列API,是Compiler API中处理类型相关逻辑的关键工具

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:08:47