I am working with ts-morph which in turns uses the TS Compiler API.
I have this case of code:
export type Foo = string
export const foo: Foo = 'bar'
When I lookup the type for the export of foo
I get string
. But what I actually want is the type alias declaration type.
The Node type of the foo
export is a VariableDeclaration. From there I figured out how to get to the TypeReferenceNode. From there I have a method to get the name of the reference. In this case "Foo"
. But I don't know how to go now from this name to the type alias declaration. Assume we don't know the location of "Foo"
type alias. How to find it out dynamically?
It's not possible in this specific situation. The TypeScript compiler interns certain types for performance reasons.
For performance reasons, we intern types where possible (this way we avoid duplicating work for equivalent types). We do not currently intern anonymous object types, though we've experimented with it before. Unfortunately, interning object types has the side effect of breaking go to definition on the interned types; so we didn't pull it in. The specific types we intern today are indexed accesses, unions, and intersections (also reverse mapped types, but only inference can produce those). This is a tradeoff - origin information is lost on interned types; but we do avoid quite a bit of work most of the time. - Source
So here, Foo
is being interned as string
since they're equivalent. I asked in the TypeScript repo if it would be feasible to disable this behaviour for analysis reasons, but didn't get a response yet.
One trick you can do to get this to work is change the code to use a brand instead of only string
.
export type Foo = string & { __FooBrand?: undefined };
export const foo: Foo = 'bar';
Additional links: