I am currently trying to build a tool where i need to resolve generic types for my final output.
Note that i am using the ts-morph library.
As an example, given the following source and the ClassDeclaration of classA as an "entry-point" for crawling types:
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>;
}
I would like to have an output like this:
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)
I am unsure how to approach this correctly. Currently, i am recursively crawling all types, starting with the base class (i use get class.getBaseClass() to also recursively crawl the base classes, i hope this is the correct/easiest way).
For the generic types i do the following:
- Wait until a generic type is encountered during crawling (e.g. on a class, or a type-alias inside the class) by checking if it has type-arguments.
- If so, get the corresponding type-parameters by jumping to the type definition (e.g. to the base class using
getBaseClass()or the interface/alias-type usinggetSymbol()orgetAliasSymbol()) - Iterate over all type-parameters and get the corresponding type-argument.
- Check if the type-argument itself has an entry in a map (explained in the next point). If so, replace the type argument with the resolved type. (This is needed for recursively defined generics)
- Save a mapping for each pair, i.e. the symbol of the i-th type-parameter to the type in the type argument
Sorry that i do not post a complete code sample for this, but i do not have a complete implementation of this yet.
My questions:
- Is this a proper way to do this? Or is there some magic typescript-compiler/ts-morph function that i overlook that achieves exactly this?
- I saw that there is a
typeChecker.getTypeOfSymbolAtLocation(..), but i am unsure how to exactly use it, and if it helps in my use-case.