diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts index afc9905faf0..bdb96222ef3 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts @@ -734,13 +734,14 @@ export class StaticInterpreter { } private visitTypeQuery(node: ts.TypeQueryNode, context: Context): ResolvedValue { - if (!ts.isIdentifier(node.exprName)) { + const exprName = ts.isQualifiedName(node.exprName) ? node.exprName.right : node.exprName; + if (!ts.isIdentifier(exprName)) { return DynamicValue.fromUnknown(node); } - const decl = this.host.getDeclarationOfIdentifier(node.exprName); + const decl = this.host.getDeclarationOfIdentifier(exprName); if (decl === null) { - return DynamicValue.fromUnknownIdentifier(node.exprName); + return DynamicValue.fromUnknownIdentifier(exprName); } const declContext: Context = {...context, ...joinModuleContext(context, node, decl)}; diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts index 53627de2d35..07cfddf5bdb 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts @@ -425,6 +425,33 @@ runInEachFileSystem(() => { expect(local.ownedByModuleGuess).toBeNull(); }); + // https://github.com/angular/angular/issues/65686 + it('supports declarations of readonly tuples with class references using qualified names', () => { + const tuple = evaluate( + ` + import * as ext from 'external'; + declare class Local {} + declare const x: readonly [typeof ext.External];`, + `x`, + [ + { + name: _('/node_modules/external/index.d.ts'), + contents: 'export declare class External {}', + }, + ], + ); + if (!Array.isArray(tuple)) { + return fail('Should have evaluated tuple as an array'); + } + const [external] = tuple; + if (!(external instanceof Reference)) { + return fail('Should have evaluated `typeof ext.External` to a Reference'); + } + expect(ts.isClassDeclaration(external.node)).toBe(true); + expect(external.debugName).toBe('External'); + expect(external.ownedByModuleGuess).toBe('external'); + }); + it('evaluates tuple elements it cannot understand to DynamicValue', () => { const value = evaluate(`declare const x: ['foo', string];`, `x`) as [string, DynamicValue];