我目前正在尝试构建一个工具,我需要为我的最终输出解析泛型类型。
请注意,我使用的是ts-morph
库。
为例,给定以下源,classA
的ClassDeclaration
为"入口点";对于爬行类型:
type X<T> = { fieldInType: T };
interface Y<T> {
fieldInInterface: T;
}
class classB<T> {
fieldInB?: T;
myFunction(a: T): void { //do something here }
}
class classA extends ClassB<string> {
interfaceField?: Y<string>;
typeField?: X<string>;
}
我希望得到这样的输出:
types of classA:
- interface Y { fieldInInterface: string } (from interfaceField)
- type X = { fieldInType: string } (from typeField)
- string (from fieldInB in parentClass)
- myFunction(a: string): void (from myFunction in parentClass)
我不确定如何正确地处理这个问题。目前,我正在递归地爬行所有类型,从基类开始(我使用getclass.getBaseClass()
也递归地爬行基类,我希望这是正确的/最简单的方法)。
对于泛型类型,我执行以下操作:
- 等待,直到在爬行过程中遇到泛型类型(例如,在类中,或类中的类型别名),检查它是否有类型参数。
- 如果是,通过跳转到类型定义获得相应的类型参数(例如,使用
getBaseClass()
跳转到基类或使用getSymbol()
或getAliasSymbol()
跳转到接口/别名类型) - 遍历所有类型参数并获得相应的类型参数。
- 检查类型参数本身是否在映射中有一个条目(在下一点解释)。如果是,则将type参数替换为解析后的类型。(这是递归需要的定义泛型)
- 为每一对保存一个映射,即第i个类型参数的符号到类型参数 中的类型
对不起,我没有发布一个完整的代码样本,但我还没有这个完整的实现。
我的问题:
- 这是正确的方法吗?还是有一些神奇的typescript-compiler/ts-morph我忽略的那个函数正好达到了这个效果?
- 我看到有一个
typeChecker.getTypeOfSymbolAtLocation(..)
,但我不确定如何确切地使用它,如果它有助于我的用例。
是的,我想你会发现getTypeAtLocation
和getTypeOfSymbolAtLocation
很有用。
查看ts-ast-viewer.com上的示例,然后在开发控制台中运行此命令:
{
const classANode = sourceFile.statements[3];
const classAType = checker.getTypeAtLocation(classANode);
for (const prop of classAType.getProperties()) {
const type = checker.getTypeOfSymbolAtLocation(prop, classANode);
console.log(prop.escapedName, checker.typeToString(type));
}
}