@@ -46,32 +46,7 @@ export function resolveType(
4646 typeStack . push ( typeId ) ;
4747 }
4848
49- // The following code handles cases where the type is a simple alias of another type (type Alias = SomeType).
50- // TypeScript resolves the alias automatically, but we want to preserve the original type symbol if it exists.
51- //
52- // However, this also covers cases where the type is a type parameter (as in `type Generic<T> = { value: T }`).
53- // Here we don't want to preserve T as a type symbol, but rather resolve it to its actual type.
54- let typeSymbol : ts . Symbol | undefined ;
55- if ( typeNode && ts . isTypeReferenceNode ( typeNode ) ) {
56- const typeNodeName = ( typeNode as ts . TypeReferenceNode ) . typeName ;
57- let typeSymbolCandidate : ts . Symbol | undefined ;
58- if ( ts . isIdentifier ( typeNodeName ) ) {
59- typeSymbolCandidate = checker . getSymbolAtLocation ( typeNodeName ) ;
60- } else if ( ts . isQualifiedName ( typeNodeName ) ) {
61- typeSymbolCandidate = checker . getSymbolAtLocation ( typeNodeName . right ) ;
62- }
63-
64- if (
65- typeSymbolCandidate &&
66- ! areEquivalent ( typeNodeName , type , checker ) &&
67- ! ( typeSymbolCandidate . flags & ts . SymbolFlags . TypeParameter )
68- ) {
69- typeSymbol = typeSymbolCandidate ;
70- }
71- }
72-
73- const typeName = getTypeName ( type , typeSymbol , checker ) ;
74- const namespaces = typeSymbol ? getTypeSymbolNamespaces ( typeSymbol ) : getTypeNamespaces ( type ) ;
49+ const { name : typeName , namespaces } = getFullyQualifiedName ( type , typeNode , checker ) ;
7550
7651 try {
7752 if ( type . flags & ts . TypeFlags . TypeParameter && type . symbol ) {
@@ -171,7 +146,7 @@ export function resolveType(
171146
172147 if ( checker . isTupleType ( type ) ) {
173148 return new TupleNode (
174- typeSymbol ?. name ?? type . aliasSymbol ?. name ,
149+ typeName ,
175150 namespaces ,
176151 ( type as ts . TupleType ) . typeArguments ?. map ( ( x ) => resolveType ( x , undefined , context ) ) ?? [ ] ,
177152 ) ;
@@ -194,11 +169,11 @@ export function resolveType(
194169 }
195170
196171 if ( type . flags & ts . TypeFlags . Any ) {
197- return new IntrinsicNode ( 'any' , typeSymbol ?. name ?? type . aliasSymbol ?. name , namespaces ) ;
172+ return new IntrinsicNode ( 'any' , typeName , namespaces ) ;
198173 }
199174
200175 if ( type . flags & ts . TypeFlags . Unknown ) {
201- return new IntrinsicNode ( 'unknown' , typeSymbol ?. name ?? type . aliasSymbol ?. name , namespaces ) ;
176+ return new IntrinsicNode ( 'unknown' , typeName , namespaces ) ;
202177 }
203178
204179 if ( type . flags & ts . TypeFlags . Literal ) {
@@ -263,7 +238,7 @@ export function resolveType(
263238 `Unable to handle a type with flag "${ ts . TypeFlags [ type . flags ] } ". Using any instead.` ,
264239 ) ;
265240
266- return new IntrinsicNode ( 'any' , typeSymbol ?. name ?? type . aliasSymbol ?. name , namespaces ) ;
241+ return new IntrinsicNode ( 'any' , typeName , namespaces ) ;
267242 } finally {
268243 typeStack . pop ( ) ;
269244 }
@@ -289,6 +264,44 @@ const allowedBuiltInReactTypes = new Set([
289264 'React.ForwardRefExoticComponent' ,
290265] ) ;
291266
267+ function getFullyQualifiedName (
268+ type : ts . Type ,
269+ typeNode : ts . TypeNode | undefined ,
270+ checker : ts . TypeChecker ,
271+ ) {
272+ // The following code handles cases where the type is a simple alias of another type (type Alias = SomeType).
273+ // TypeScript resolves the alias automatically, but we want to preserve the original type symbol if it exists.
274+ //
275+ // However, this also covers cases where the type is a type parameter (as in `type Generic<T> = { value: T }`).
276+ // Here we don't want to preserve T as a type symbol, but rather resolve it to its actual type.
277+ let typeSymbol : ts . Symbol | undefined ;
278+ if ( typeNode && ts . isTypeReferenceNode ( typeNode ) ) {
279+ const typeNodeName = ( typeNode as ts . TypeReferenceNode ) . typeName ;
280+ let typeSymbolCandidate : ts . Symbol | undefined ;
281+ if ( ts . isIdentifier ( typeNodeName ) ) {
282+ typeSymbolCandidate = checker . getSymbolAtLocation ( typeNodeName ) ;
283+ } else if ( ts . isQualifiedName ( typeNodeName ) ) {
284+ typeSymbolCandidate = checker . getSymbolAtLocation ( typeNodeName . right ) ;
285+ }
286+
287+ if (
288+ typeSymbolCandidate &&
289+ ! areEquivalent ( typeNodeName , type , checker ) &&
290+ ! ( typeSymbolCandidate . flags & ts . SymbolFlags . TypeParameter )
291+ ) {
292+ typeSymbol = typeSymbolCandidate ;
293+ }
294+ }
295+
296+ const name = getTypeName ( type , typeSymbol , checker ) ;
297+ const namespaces = typeSymbol ? getTypeSymbolNamespaces ( typeSymbol ) : getTypeNamespaces ( type ) ;
298+
299+ return {
300+ name,
301+ namespaces,
302+ } ;
303+ }
304+
292305export function getTypeNamespaces ( type : ts . Type ) : string [ ] {
293306 const symbol = type . aliasSymbol ?? type . getSymbol ( ) ;
294307 if ( ! symbol ) {
0 commit comments