如何使用 TypeScript 编译器 API 对使用 `require()` 导入的模块进行类型检查?

How to use the TypeScript Compiler API to type-check modules imported using `require()`?

我正在使用 TypeScript Compiler API 中的 TypeChecker 来为我程序的 AST 中的每个节点提取(推断)类型信息。特别是,我尝试从导入的模块函数中找出 return 值,例如:

var vec3 = require('gl-matrix/vec3')
var myVec = vec3.fromValues(1, 2, 3) // $ExpectedType vec3

这适用于使用 import { … } from '…' 语句导入的模块,但不幸的是,无法正确识别像上面那样使用 require() 导入的模块,我只收到类型 any 给他们。但是,我已经设置了编译器选项 allowJscheckJs.

为什么无法正确推断 require()d 模块的类型? VS 代码(AFAIK 依赖于相同的 API?)能够也可以从 require() 语句中推断出类型,所以我猜一般情况下,tsc 能够处理它们。是否还有其他编译器选项需要我进行不同的设置?或者这确实不受支持,我需要为此使用其他包吗?

这是一个最小的复制脚本,我也把它和两个示例文件一起放在 repl.it 上:https://replit.com/@LinqLover/typecheck-js

var ts = require("typescript")

// Run `node index.js sample-import.js`` to see the working TypeScript analysis
const files = process.argv[1] != "/run_dir/interp.js" ? process.argv.slice(2) : ["sample-require.js"]
console.log(`Analyzing ${files}:`)
const program = ts.createProgram(files, {
  target: ts.ScriptTarget.ES5,
  module: ts.ModuleKind.CommonJS,
  allowJs: true,
  checkJs: true
})
const checker = program.getTypeChecker()

for (const sourceFile of program.getSourceFiles()) {
  if (!sourceFile.isDeclarationFile) {
      ts.forEachChild(sourceFile, visit)
  }
}

function visit(node) {
  try {
    const type = checker.getTypeAtLocation(node)
    console.log(checker.typeToString(type))
  } catch (e) {
    // EAFP
  }
  ts.forEachChild(node, visit)
}

在此先感谢您!

后续发现这是 gl-matrix 类型定义的问题。在怀疑 TypeScript 引擎本身可能被破坏之前,我最好尝试多个包 ...

gl-matrix 问题:https://github.com/toji/gl-matrix/issues/429