Skip to content

Commit 2d6d5db

Browse files
authored
Fix getTypeAtLocation for dotted implements clauses (#39363)
* Fix getTypeAtLocation for dotted implements clauses * Fix typo
1 parent b7193a6 commit 2d6d5db

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14387,11 +14387,12 @@ namespace ts {
1438714387
return getTypeFromInferTypeNode(<InferTypeNode>node);
1438814388
case SyntaxKind.ImportType:
1438914389
return getTypeFromImportTypeNode(<ImportTypeNode>node);
14390-
// This function assumes that an identifier or qualified name is a type expression
14390+
// This function assumes that an identifier, qualified name, or property access expression is a type expression
1439114391
// Callers should first ensure this by calling `isPartOfTypeNode`
1439214392
// TODO(rbuckton): These aren't valid TypeNodes, but we treat them as such because of `isPartOfTypeNode`, which returns `true` for things that aren't `TypeNode`s.
1439314393
case SyntaxKind.Identifier as TypeNodeSyntaxKind:
1439414394
case SyntaxKind.QualifiedName as TypeNodeSyntaxKind:
14395+
case SyntaxKind.PropertyAccessExpression as TypeNodeSyntaxKind:
1439514396
const symbol = getSymbolAtLocation(node);
1439614397
return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType;
1439714398
default:

src/testRunner/unittests/publicApi.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,31 @@ describe("unittests:: Public APIs:: isPropertyName", () => {
7777
assert.isTrue(ts.isPropertyName(prop), "PrivateIdentifier must be a valid property name.");
7878
});
7979
});
80+
81+
describe("unittests:: Public APIs:: getTypeAtLocation", () => {
82+
it("works on PropertyAccessExpression in implements clause", () => {
83+
const content = `namespace Test {
84+
export interface Test {}
85+
}
86+
class Foo implements Test.Test {}`;
87+
88+
const host = new fakes.CompilerHost(vfs.createFromFileSystem(
89+
Harness.IO,
90+
/*ignoreCase*/ true,
91+
{ documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" }));
92+
93+
const program = ts.createProgram({
94+
host,
95+
rootNames: ["/file.ts"],
96+
options: { noLib: true }
97+
});
98+
99+
const checker = program.getTypeChecker();
100+
const file = program.getSourceFile("/file.ts")!;
101+
const classDeclaration = file.statements.find(ts.isClassDeclaration)!;
102+
const propertyAccess = classDeclaration.heritageClauses![0].types[0].expression as ts.PropertyAccessExpression;
103+
const type = checker.getTypeAtLocation(propertyAccess);
104+
assert.ok(!(type.flags & ts.TypeFlags.Any));
105+
assert.equal(type, checker.getTypeAtLocation(propertyAccess.name));
106+
});
107+
});

0 commit comments

Comments
 (0)