我在文件中有一个名为Commands
的映射类型,如下所示:
// File: protocol.ts
import { CArgs, CRes } from '../utils';
type S = import('src/applications').Services;
export type Commands = {
-readonly [P in keyof S]: {
args: CArgs<S[P]>;
res: CRes<S[P]>;
};
};
// ... more declarations
推论非常复杂,Services
本身就是一种映射类型,它是使用UnionToIntersection
和更多奇特的事物推论得出的,其类型来自许多不同的文件...但是它可以工作并且由TypeScript推断的类型是这样的:
type Commands = {
Com1: {
args: number;
res: void;
};
Com2: {
args: {foo: string};
res: string[];
};
// ... etc ...
};
现在,我想发出一个具有 resolved类型的单个.d.ts
文件,如第二个片段所示,因此客户端不需要整个文件树的声明来推断方式。换句话说,我想“粘贴”从TypeScript推断出的类型,替换Commands
声明并删除所有import语句。
我认为我需要使用编译器API,但是我能找到的小型文档不是很清楚。老实说,我什至不知道从哪里开始。
我如何执行该任务?
我首先使用给出文件名Program
的{{1}}创建了ts.createProgram()
。我从那里访问了每个节点,所以我知道文件已加载。我创建了一个protocol.ts
,几乎每个TypeChecker
都使用了.getTypeAtLocation()
,记录了Node
,checker.typeToString(type)
等,但是没有推断类型的踪迹。也许类型检查器或程序需要加载每个文件? (我以为它会自己做)如果是这样,如何从checker.GetFullyQualifiedName(type.symbol)
中的glob模式创建数组?
如您所见,我有点迷失了,欢迎任何帮助和指导。
非常感谢您。
答案 0 :(得分:0)
我几乎可以肯定,还有一种更好的方法,但是在编译器API的incremental example之后,我能够获得与VSCode显示的信息相同的信息。
给出./src/mapped-types.ts
是:
type A = { a: 1, b: 2, c: 3 }
export type Mapped = {
readonly [K in keyof A]: A[K]
}
将输出以下代码:
type Mapped = {
readonly a: 1;
readonly b: 2;
readonly c: 3;
}
import * as ts from 'typescript'
import * as fs from 'fs'
const rootFileNames = ['./src/mapped-types.ts']
const files: ts.MapLike<{ version: number }> = {};
const servicesHost: ts.LanguageServiceHost = {
getScriptFileNames: () => rootFileNames,
getScriptVersion: fileName => files[fileName] && files[fileName].version.toString(),
getScriptSnapshot: fileName => {
if (!fs.existsSync(fileName)) {
return undefined;
}
return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString());
},
getCurrentDirectory: () => process.cwd(),
getCompilationSettings: () => ({}),
getDefaultLibFileName: options => ts.getDefaultLibFilePath(options),
fileExists: ts.sys.fileExists,
readFile: ts.sys.readFile,
readDirectory: ts.sys.readDirectory
};
// Create the language service files
const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry());
const index = fs.readFileSync(rootFileNames[0], 'utf-8').indexOf('Mapped')
const info = services.getQuickInfoAtPosition(rootFileNames[0], index)!
console.log(ts.displayPartsToString(info.displayParts))
获取快速信息的相关代码是here,不幸的是那里发生了很多我不理解的事情,所以我不确定如何向正确的方向指出。