使用编译器api获取typescript中的变量类型

时间:2018-05-06 13:47:05

标签: typescript

我似乎无法使用编译器API获取变量的类型。 下面我的示例的一些上下文。 因为我在内存中运行所有内容,所以我必须创建自己的编译器主机。这是必要的,因为类型检查器是从“程序”创建的。并且这要求默认文件写入磁盘。

我尝试输入"输入"和" el"。我希望这打印出来#34;数字[]"和"数字"。这就像我将鼠标悬停在VSCode上一样。

然而,我得到的输出是" {}"或"任何"。

我确定我做错了什么或忘记了什么,但我不知道它是什么。

祝你好运, 艾克

const code: string = `let input: number[] = [1, 2, 3];
for (let el of input) {
    let x = el * 3;
    if (el > 1) {
        output.push(el);
    }
}`;

const host: ts.CompilerHost = {
  getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void): ts.SourceFile {
    console.log("getSourceFile", fileName);
    if (fileName === "test.ts") {
        return ts.createSourceFile(fileName, code, languageVersion);
    }
    if (onError) {
        onError("not found");
    }
    // tsc's declarations don't support strict null checks
    return null as any as ts.SourceFile;
  },
  getDefaultLibFileName: () => "", // "lib.d.ts",
  writeFile: (_fileName, _content) => { },
  getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
  getCanonicalFileName: fileName => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
  getNewLine: () => ts.sys.newLine,
  useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
  fileExists: (fileName: string) => fileName === "test.ts",
  readFile(fileName: string): string {
    if (fileName === "test.ts") {
      return code;
    }
    return null as any as string;
  },
  resolveModuleNames(_moduleNames: string[], _containingFile: string): ts.ResolvedModule[] {
    throw new Error("unsupported");
  },
  getDirectories(_path: string): string[] {
    throw new Error("unsupported");
  }
};


const program: ts.Program = ts.createProgram(["test.ts"], {allowJs: true}, host);
const checker: ts.TypeChecker = program.getTypeChecker();
const forofke: ts.ForOfStatement = program.getSourceFiles()[0].statements[1];
const stat = forofke.expression;
const type1: ts.Type = checker.getTypeAtLocation(stat);
console.log(checker.typeToString(type1));
const sym: ts.Symbol = checker.getSymbolAtLocation(stat);
const type2: ts.Type = checker.getDeclaredTypeOfSymbol(sym);
console.log(checker.typeToString(type2));
const type3: ts.Type = checker.getTypeOfSymbolAtLocation(sym, stat);
console.log(checker.typeToString(type3));
const type4: ts.Type = checker.getTypeOfSymbolAtLocation(sym, sym.valueDeclaration);
console.log(checker.typeToString(type4));

const stat2 = (<ts.VariableDeclarationList>forofke.initializer).declarations[0].name;
const type12: ts.Type = checker.getTypeAtLocation(stat2);
console.log(checker.typeToString(type12));
const sym2: ts.Symbol = checker.getSymbolAtLocation(stat2);
const type22: ts.Type = checker.getDeclaredTypeOfSymbol(sym2);
console.log(checker.typeToString(type22));
const type32: ts.Type = checker.getTypeOfSymbolAtLocation(sym2, stat2);
console.log(checker.typeToString(type32));
const type42: ts.Type = checker.getTypeOfSymbolAtLocation(sym2, sym2.valueDeclaration);
console.log(checker.typeToString(type42));

1 个答案:

答案 0 :(得分:0)

我比较了一个&#39;程序&#39;从我的样本中从磁盘加载到内存中的那个。我注意到,从磁盘中有两个源文件,在program.getSourceFiles()&#39;中。第二个文件是lib.d.ts。

我稍微更改了我的样本,现在输出就像我预期的那样。

  getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void): ts.SourceFile {
    console.log("getSourceFile", fileName);
    if (fileName === "test.ts") {
        return ts.createSourceFile(fileName, code, languageVersion);
    }
    if (fileName === "lib.d.ts") {
        return ts.createSourceFile(fileName, /*READ the file from disk*/, languageVersion);
    }
    if (onError) {
        onError("not found");
    }
    // tsc's declarations don't support strict null checks
    return null as any as ts.SourceFile;
  },
  getDefaultLibFileName: () => "lib.d.ts",