From 43d61ecbb224ec47434dfc285fd14c7da0dd4aac Mon Sep 17 00:00:00 2001 From: Matthieu Riegler Date: Tue, 3 Feb 2026 10:50:46 +0100 Subject: [PATCH] docs(docs-infra): extract call signature return type. fixes #66799 --- .../src/ngtsc/docs/src/function_extractor.ts | 15 +++++++++-- .../interface_doc_extraction_spec.ts | 25 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/docs/src/function_extractor.ts b/packages/compiler-cli/src/ngtsc/docs/src/function_extractor.ts index 8ce14b220ec..68decde1e83 100644 --- a/packages/compiler-cli/src/ngtsc/docs/src/function_extractor.ts +++ b/packages/compiler-cli/src/ngtsc/docs/src/function_extractor.ts @@ -152,12 +152,23 @@ function extractReturnType(signature: ts.Signature, typeChecker: ts.TypeChecker) return signature.declaration.type.getText(); } - return typeChecker.typeToString( - typeChecker.getReturnTypeOfSignature(signature), + const returnType = typeChecker.getReturnTypeOfSignature(signature); + const returnTypeString = typeChecker.typeToString( + returnType, undefined, // This ensures that e.g. `T | undefined` is not reduced to `T`. ts.TypeFormatFlags.NoTypeReduction | ts.TypeFormatFlags.NoTruncation, ); + + if ( + returnTypeString === 'any' && + signature.declaration?.type && + signature.declaration.type.kind !== ts.SyntaxKind.AnyKeyword + ) { + return signature.declaration.type.getText(); + } + + return returnTypeString; } /** Finds the implementation of the given function declaration overload signature. */ diff --git a/packages/compiler-cli/test/ngtsc/doc_extraction/interface_doc_extraction_spec.ts b/packages/compiler-cli/test/ngtsc/doc_extraction/interface_doc_extraction_spec.ts index 8bca93e4163..a76fb56db3f 100644 --- a/packages/compiler-cli/test/ngtsc/doc_extraction/interface_doc_extraction_spec.ts +++ b/packages/compiler-cli/test/ngtsc/doc_extraction/interface_doc_extraction_spec.ts @@ -8,7 +8,6 @@ import {DocEntry} from '../../../src/ngtsc/docs'; import { - ClassEntry, EntryType, InterfaceEntry, MemberTags, @@ -382,5 +381,29 @@ runInEachFileSystem(() => { expect(ageSetterEntry.type).toBe('number'); expect(ageSetterEntry.memberTags).toContain(MemberTags.Inherited); }); + + it('should extract return type for call signature', () => { + env.write( + 'index.ts', + ` + export interface AsyncValidatorFn { + ( + control: AbstractControl, + ): Promise | Observable; + } + `, + ); + + const docs: DocEntry[] = env.driveDocsExtraction('index.ts'); + const interfaceEntry = docs[0] as InterfaceEntry; + expect(interfaceEntry.members.length).toBe(1); + + const methodEntry = interfaceEntry.members[0] as MethodEntry; + expect(methodEntry.memberType).toBe(MemberType.Method); + expect(methodEntry.name).toBe(''); + expect(methodEntry.implementation.returnType).toBe( + 'Promise | Observable', + ); + }); }); });