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

如何查找代码库中所有属于或包含指定TypeScript类型的变量位置

TypeScript静态查找所有持有指定类型变量的实现方案

你可以通过TypeScript官方Compiler API结合类型兼容性校验实现该需求,核心是调用TypeChecker暴露的isTypeAssignableTo方法完成类型匹配,具体步骤如下:

  • 第一步:加载代码库拿到目标类型实例
    调用ts.createProgram加载你的整个代码库得到Program实例,再通过program.getTypeChecker()获取TypeChecker实例。遍历所有源文件的AST定位到SomeObject的类型别名声明节点,调用checker.getTypeAtLocation(类型声明节点)拿到目标类型对象targetType。
  • 第二步:全量遍历AST匹配类型节点
    遍历所有源文件的所有AST节点,对每个变量声明节点、标识符节点、对象属性节点等可能持有值的节点,调用checker.getTypeAtLocation(节点)获取该节点对应的推导类型currentType。
  • 第三步:类型兼容性校验
    调用checker.isTypeAssignableTo(currentType, targetType),返回true即说明该节点的类型和SomeObject兼容,属于你要找的持有该类型数据的节点。
    如果要覆盖嵌套使用的场景,额外递归遍历对象类型的所有属性,对每个属性的类型再执行上述兼容性校验,属性类型匹配时对应父节点也需要纳入结果。

你可以参考以下最简实现代码:

import * as ts from 'typescript';

// 初始化Program加载整个代码库
const program = ts.createProgram(['src/**/*.ts'], {
  strict: true, // 保持和你项目一致的TS配置即可
});
const checker = program.getTypeChecker();

let targetType: ts.Type;
// 定位目标类型SomeObject
for (const sourceFile of program.getSourceFiles()) {
  if (!sourceFile.isDeclarationFile) { // 跳过d.ts声明文件可按需调整
    ts.forEachChild(sourceFile, (node) => {
      if (ts.isTypeAliasDeclaration(node) && node.name.text === 'SomeObject') {
        targetType = checker.getTypeAtLocation(node);
      }
    });
  }
  if (targetType) break;
}

const matchedNodes: ts.Node[] = [];
// 遍历所有节点查找匹配项
for (const sourceFile of program.getSourceFiles()) {
  if (!sourceFile.isDeclarationFile) {
    ts.forEachChild(sourceFile, function traverse(node: ts.Node) {
      // 跳过类型声明本身
      if (ts.isTypeAliasDeclaration(node) && node.name.text === 'SomeObject') return;
      try {
        const currentType = checker.getTypeAtLocation(node);
        // 直接匹配类型
        if (checker.isTypeAssignableTo(currentType, targetType)) {
          matchedNodes.push(node);
          return;
        }
        // 检查嵌套属性
        const props = currentType.getProperties();
        for (const prop of props) {
          const propType = checker.getTypeOfSymbolAtLocation(prop, node);
          if (checker.isTypeAssignableTo(propType, targetType)) {
            matchedNodes.push(node);
            break;
          }
        }
      } catch (e) {
        // 忽略无法推导类型的节点
      }
      // 递归遍历子节点
      ts.forEachChild(node, traverse);
    });
  }
}

// 输出所有匹配节点的位置信息
matchedNodes.forEach(node => {
  const sf = node.getSourceFile();
  const { line, character } = ts.getLineAndCharacterOfPosition(sf, node.getStart());
  console.log(`匹配位置:${sf.fileName}:${line + 1}:${character + 1}`);
});

注意事项

  • 你可以按需过滤节点类型,比如只保留变量声明、函数参数、类属性等节点,排除临时字面量节点即可适配不同的查找需求。
  • 解构、对象展开等语法场景下TypeChecker会自动完成类型推导,不需要额外做特殊语法适配,isTypeAssignableTo可以正确识别兼容类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:39:04