typescript - 使用编译器 api 在 typescript 中获取变量的类型
问题描述
我似乎无法使用编译器 API 获取变量的类型。下面是我的示例的一些上下文。由于我在内存中运行所有内容,因此我必须创建自己的编译器主机。这是必需的,因为类型检查器是从“程序”创建的,并且默认情况下需要将文件写入磁盘。
我尝试获取“输入”和“el”的类型。我希望这能打印出“number[]”和“number”。这就像我在 VSCode 中将鼠标悬停在它上面一样。
但是,我得到的输出是“{}”或“any”。
我确定我做错了什么或者我忘记了什么,但我不明白它是什么。
最好的问候,艾克
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));
解决方案
我将一个从磁盘加载的“程序”与我的示例中的内存中的一个进行了比较。我注意到从磁盘上'program.getSourceFiles()'中有2个源文件。第二个文件是 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",
推荐阅读
- delphi - 使用 BASS dll 和 Delphi 创建 flac 文件或 flac 流
- stata - 幂二均值:均值必须包含数字
- git - mac上的git-svn无法连接到远程svn仓库,而simple svn可以
- php - LOAD DATA INFILE 父子表和外键关系
- create-react-app - 如何通过 create-react-app 在远程开发盒上使用 npm start
- r - 将列表中的多个 data.tables 组合成两个 data.tables 的列表
- bit-framework - 如何在配置 json 文件中嵌套配置并使用位读取它?
- .net - list.Clear() 与 new List<>() - ASP.NET Core - Entity Framework Core - 延迟加载
- grep - 大输出的 grep、求和和平均值
- vba - 为什么输入 Worksheets("Sheet1"). 后没有出现 Intellisense?