launch.json直接配置一个测试调试
{
"type": "node",
"request": "launch",
"name": "Debug Infer Test",
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
"args": [
"${workspaceFolder}/packages/type-compiler/tests/transpile.spec.ts",
"--runInBand",
"--no-cache"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"sourceMaps": true,
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest.js"
}
},
直接修改test里要transpile的代码,type-compiler里的createProgram/transformSourceFile
里加断点,就可以了
const res = transpile({
'app': `
type Text222<T> = T extends boolean ? 'y' : 'n';
type test1 = Text222<boolean | string>;
`
},
具体例子
对于代码:
type Text222<T> = T extends boolean ? 'y' : 'n';
type test1 = Text222<boolean | string>;
首先从 transformSourceFile
开始:
transformSourceFile(sourceFile: SourceFile): SourceFile {
// 初始化转换过程
this.sourceFile = sourceFile;
const visitor = (node: Node): any => {
node = visitEachChild(node, visitor, this.context);
// 处理类型别名声明
if (isTypeAliasDeclaration(node)) {
this.compileDeclarations.set(node, {
name: node.name,
sourceFile: this.sourceFile,
});
}
return node;
};
this.sourceFile = visitNode(this.sourceFile, visitor);
}
当遇到 Text222<T>
定义时,会调用 createProgramVarFromNode
:
protected createProgramVarFromNode(node: Node, name: EntityName, sourceFile?: SourceFile): Statement[] {
const typeProgram = new CompilerProgram(node, sourceFile);
// 处理类型参数
if (node.typeParameters) {
for (const param of node.typeParameters) {
typeProgram.pushTemplateParameter(getIdentifierName(param.name));
}
}
// 提取类型结构
this.extractPackStructOfType(node, typeProgram);
}
然后进入 extractPackStructOfType
处理条件类型:
case SyntaxKind.ConditionalType: {
const narrowed = node as ConditionalTypeNode;
// 处理条件类型
program.pushConditionalFrame();
this.extractPackStructOfType(narrowed.checkType, program); // T
this.extractPackStructOfType(narrowed.extendsType, program); // boolean
program.pushOp(ReflectionOp.extends);
// 处理 true 分支
program.pushCoRoutine();
this.extractPackStructOfType(narrowed.trueType, program); // 'y'
const trueProgram = program.popCoRoutine();
// 处理 false 分支
program.pushCoRoutine();
this.extractPackStructOfType(narrowed.falseType, program); // 'n'
const falseProgram = program.popCoRoutine();
program.pushOp(ReflectionOp.jumpCondition, trueProgram, falseProgram);
}
当处理 test1 = Text222<boolean | string>
时,会进入 extractPackStructOfTypeReference
:
protected extractPackStructOfTypeReference(type: TypeReferenceNode, program: CompilerProgram): void {
// 处理类型参数
if (type.typeArguments) {
for (const argument of type.typeArguments) {
this.extractPackStructOfType(argument, program);
}
}
// 处理联合类型
if (isUnionTypeNode(type.typeArguments[0])) {
program.pushFrame();
for (const subType of type.typeArguments[0].types) {
this.extractPackStructOfType(subType, program);
}
program.pushOp(ReflectionOp.union);
}
}
最终会生成一个包含以下操作码的程序:
// 对于 Text222<T>
[
ReflectionOp.typeParameter, // T
ReflectionOp.boolean, // boolean
ReflectionOp.extends, // extends
ReflectionOp.jumpCondition, // ?
ReflectionOp.literal, // 'y'
ReflectionOp.literal, // 'n'
]
// 对于 test1
[
ReflectionOp.boolean, // boolean
ReflectionOp.string, // string
ReflectionOp.union, // |
ReflectionOp.inlineCall // 应用 Text222
]