fix(compiler-cli): support qualified names in typeof type references

This commit expands the static interpreter to now understand qualified names in `typeof`
type queries.

Fixes #65686

(cherry picked from commit f12e160bc1)
This commit is contained in:
JoostK 2025-12-22 20:31:11 +01:00 committed by Kristiyan Kostadinov
parent 4d9c4567ed
commit 778460fcca
2 changed files with 31 additions and 3 deletions

View file

@ -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)};

View file

@ -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];