@@ -7,6 +7,7 @@ import type { BaseType } from "../Type/BaseType.js";
77import { UnionType } from "../Type/UnionType.js" ;
88import { LiteralType } from "../Type/LiteralType.js" ;
99import { SymbolType } from "../Type/SymbolType.js" ;
10+ import { UnknownNodeError } from "../Error/Errors.js" ;
1011
1112export class CallExpressionParser implements SubNodeParser {
1213 public constructor (
@@ -33,9 +34,21 @@ export class CallExpressionParser implements SubNodeParser {
3334 }
3435
3536 const symbol = type . symbol || type . aliasSymbol ;
36- const decl = symbol . valueDeclaration || symbol . declarations ! [ 0 ] ;
37- const subContext = this . createSubContext ( node , context ) ;
38- return this . childNodeParser . createType ( decl , subContext ) ;
37+
38+ // For funtions like <T>(type: T) => T, there won't be any reference to the original
39+ // type. Using type checker to infer the actual return type without mapping the whole
40+ // function and back referencing its generic type based on parameter index is a better
41+ // approach.
42+ const decl =
43+ this . typeChecker . typeToTypeNode ( type , node , ts . NodeBuilderFlags . IgnoreErrors ) ||
44+ symbol . valueDeclaration ||
45+ symbol . declarations ?. [ 0 ] ;
46+
47+ if ( ! decl ) {
48+ throw new UnknownNodeError ( node ) ;
49+ }
50+
51+ return this . childNodeParser . createType ( decl , this . createSubContext ( node , context ) ) ;
3952 }
4053
4154 protected createSubContext ( node : ts . CallExpression , parentContext : Context ) : Context {
0 commit comments