diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 4cc0bb79531..319caa180c3 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -13123,6 +13123,12 @@ namespace ts {
return type;
}
+ function markAliasReferenced(symbol: Symbol, location: Node) {
+ if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
+ markAliasSymbolAsReferenced(symbol);
+ }
+ }
+
function checkIdentifier(node: Identifier): Type {
const symbol = getResolvedSymbol(node);
if (symbol === unknownSymbol) {
@@ -13151,9 +13157,9 @@ namespace ts {
}
// We should only mark aliases as referenced if there isn't a local value declaration
- // for the symbol.
- if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
- markAliasSymbolAsReferenced(symbol);
+ // for the symbol. Also, don't mark any property access expression LHS - checkPropertyAccessExpression will handle that
+ if (!(node.parent && isPropertyAccessExpression(node.parent) && node.parent.expression === node)) {
+ markAliasReferenced(symbol, node);
}
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
@@ -15711,15 +15717,20 @@ namespace ts {
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
let propType: Type;
- let leftSymbol = getNodeLinks(left) && getNodeLinks(left).resolvedSymbol;
- const leftWasReferenced = leftSymbol && getSymbolLinks(leftSymbol).referenced;
const leftType = checkNonNullExpression(left);
+ const parentSymbol = getNodeLinks(left).resolvedSymbol;
const apparentType = getApparentType(getWidenedType(leftType));
if (isTypeAny(apparentType) || apparentType === silentNeverType) {
+ if (isIdentifier(left) && parentSymbol) {
+ markAliasReferenced(parentSymbol, node);
+ }
return apparentType;
}
const assignmentKind = getAssignmentTargetKind(node);
const prop = getPropertyOfType(apparentType, right.escapedText);
+ if (isIdentifier(left) && parentSymbol && !(prop && isConstEnumOrConstEnumOnlyModule(prop))) {
+ markAliasReferenced(parentSymbol, node);
+ }
if (!prop) {
const indexInfo = getIndexInfoOfType(apparentType, IndexKind.String);
if (!(indexInfo && indexInfo.type)) {
@@ -15736,13 +15747,6 @@ namespace ts {
else {
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
- // Reset the referenced-ness of the LHS expression if this access refers to a const enum or const enum only module
- leftSymbol = getNodeLinks(left) && getNodeLinks(left).resolvedSymbol;
- if (leftSymbol && !leftWasReferenced && getSymbolLinks(leftSymbol).referenced &&
- !(isNonLocalAlias(leftSymbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(prop))
- ) {
- getSymbolLinks(leftSymbol).referenced = undefined;
- }
getNodeLinks(node).resolvedSymbol = prop;
checkPropertyAccessibility(node, left, apparentType, prop);
if (assignmentKind) {
diff --git a/tests/baselines/reference/importAliasFromNamespace.js b/tests/baselines/reference/importAliasFromNamespace.js
new file mode 100644
index 00000000000..57bfab58d9a
--- /dev/null
+++ b/tests/baselines/reference/importAliasFromNamespace.js
@@ -0,0 +1,68 @@
+//// [tests/cases/compiler/importAliasFromNamespace.ts] ////
+
+//// [internal.ts]
+namespace My.Internal {
+ export function getThing(): void {}
+ export const enum WhichThing {
+ A, B, C
+ }
+}
+
+//// [usage.ts]
+///
+namespace SomeOther.Thing {
+ import Internal = My.Internal;
+ export class Foo {
+ private _which: Internal.WhichThing;
+ constructor() {
+ Internal.getThing();
+ Internal.WhichThing.A ? "foo" : "bar";
+ }
+ }
+}
+
+//// [internal.js]
+var My;
+(function (My) {
+ var Internal;
+ (function (Internal) {
+ function getThing() { }
+ Internal.getThing = getThing;
+ })(Internal = My.Internal || (My.Internal = {}));
+})(My || (My = {}));
+//// [usage.js]
+///
+var SomeOther;
+(function (SomeOther) {
+ var Thing;
+ (function (Thing) {
+ var Internal = My.Internal;
+ var Foo = /** @class */ (function () {
+ function Foo() {
+ Internal.getThing();
+ 0 /* A */ ? "foo" : "bar";
+ }
+ return Foo;
+ }());
+ Thing.Foo = Foo;
+ })(Thing = SomeOther.Thing || (SomeOther.Thing = {}));
+})(SomeOther || (SomeOther = {}));
+
+
+//// [internal.d.ts]
+declare namespace My.Internal {
+ function getThing(): void;
+ const enum WhichThing {
+ A = 0,
+ B = 1,
+ C = 2,
+ }
+}
+//// [usage.d.ts]
+///
+declare namespace SomeOther.Thing {
+ class Foo {
+ private _which;
+ constructor();
+ }
+}
diff --git a/tests/baselines/reference/importAliasFromNamespace.symbols b/tests/baselines/reference/importAliasFromNamespace.symbols
new file mode 100644
index 00000000000..11cbb52d895
--- /dev/null
+++ b/tests/baselines/reference/importAliasFromNamespace.symbols
@@ -0,0 +1,52 @@
+=== tests/cases/compiler/usage.ts ===
+///
+namespace SomeOther.Thing {
+>SomeOther : Symbol(SomeOther, Decl(usage.ts, 0, 0))
+>Thing : Symbol(Thing, Decl(usage.ts, 1, 20))
+
+ import Internal = My.Internal;
+>Internal : Symbol(Internal, Decl(usage.ts, 1, 27))
+>My : Symbol(My, Decl(internal.ts, 0, 0))
+>Internal : Symbol(Internal, Decl(internal.ts, 0, 13))
+
+ export class Foo {
+>Foo : Symbol(Foo, Decl(usage.ts, 2, 34))
+
+ private _which: Internal.WhichThing;
+>_which : Symbol(Foo._which, Decl(usage.ts, 3, 22))
+>Internal : Symbol(Internal, Decl(usage.ts, 1, 27))
+>WhichThing : Symbol(Internal.WhichThing, Decl(internal.ts, 1, 39))
+
+ constructor() {
+ Internal.getThing();
+>Internal.getThing : Symbol(Internal.getThing, Decl(internal.ts, 0, 23))
+>Internal : Symbol(Internal, Decl(usage.ts, 1, 27))
+>getThing : Symbol(Internal.getThing, Decl(internal.ts, 0, 23))
+
+ Internal.WhichThing.A ? "foo" : "bar";
+>Internal.WhichThing.A : Symbol(Internal.WhichThing.A, Decl(internal.ts, 2, 34))
+>Internal.WhichThing : Symbol(Internal.WhichThing, Decl(internal.ts, 1, 39))
+>Internal : Symbol(Internal, Decl(usage.ts, 1, 27))
+>WhichThing : Symbol(Internal.WhichThing, Decl(internal.ts, 1, 39))
+>A : Symbol(Internal.WhichThing.A, Decl(internal.ts, 2, 34))
+ }
+ }
+}
+=== tests/cases/compiler/internal.ts ===
+namespace My.Internal {
+>My : Symbol(My, Decl(internal.ts, 0, 0))
+>Internal : Symbol(Internal, Decl(internal.ts, 0, 13))
+
+ export function getThing(): void {}
+>getThing : Symbol(getThing, Decl(internal.ts, 0, 23))
+
+ export const enum WhichThing {
+>WhichThing : Symbol(WhichThing, Decl(internal.ts, 1, 39))
+
+ A, B, C
+>A : Symbol(WhichThing.A, Decl(internal.ts, 2, 34))
+>B : Symbol(WhichThing.B, Decl(internal.ts, 3, 10))
+>C : Symbol(WhichThing.C, Decl(internal.ts, 3, 13))
+ }
+}
+
diff --git a/tests/baselines/reference/importAliasFromNamespace.types b/tests/baselines/reference/importAliasFromNamespace.types
new file mode 100644
index 00000000000..9bc6cbf0d18
--- /dev/null
+++ b/tests/baselines/reference/importAliasFromNamespace.types
@@ -0,0 +1,56 @@
+=== tests/cases/compiler/usage.ts ===
+///
+namespace SomeOther.Thing {
+>SomeOther : typeof SomeOther
+>Thing : typeof Thing
+
+ import Internal = My.Internal;
+>Internal : typeof Internal
+>My : typeof My
+>Internal : typeof Internal
+
+ export class Foo {
+>Foo : Foo
+
+ private _which: Internal.WhichThing;
+>_which : Internal.WhichThing
+>Internal : any
+>WhichThing : Internal.WhichThing
+
+ constructor() {
+ Internal.getThing();
+>Internal.getThing() : void
+>Internal.getThing : () => void
+>Internal : typeof Internal
+>getThing : () => void
+
+ Internal.WhichThing.A ? "foo" : "bar";
+>Internal.WhichThing.A ? "foo" : "bar" : "foo" | "bar"
+>Internal.WhichThing.A : Internal.WhichThing.A
+>Internal.WhichThing : typeof Internal.WhichThing
+>Internal : typeof Internal
+>WhichThing : typeof Internal.WhichThing
+>A : Internal.WhichThing.A
+>"foo" : "foo"
+>"bar" : "bar"
+ }
+ }
+}
+=== tests/cases/compiler/internal.ts ===
+namespace My.Internal {
+>My : typeof My
+>Internal : typeof Internal
+
+ export function getThing(): void {}
+>getThing : () => void
+
+ export const enum WhichThing {
+>WhichThing : WhichThing
+
+ A, B, C
+>A : WhichThing.A
+>B : WhichThing.B
+>C : WhichThing.C
+ }
+}
+
diff --git a/tests/cases/compiler/importAliasFromNamespace.ts b/tests/cases/compiler/importAliasFromNamespace.ts
new file mode 100644
index 00000000000..c7958be7e2c
--- /dev/null
+++ b/tests/cases/compiler/importAliasFromNamespace.ts
@@ -0,0 +1,21 @@
+// @declaration: true
+// @filename: internal.ts
+namespace My.Internal {
+ export function getThing(): void {}
+ export const enum WhichThing {
+ A, B, C
+ }
+}
+
+// @filename: usage.ts
+///
+namespace SomeOther.Thing {
+ import Internal = My.Internal;
+ export class Foo {
+ private _which: Internal.WhichThing;
+ constructor() {
+ Internal.getThing();
+ Internal.WhichThing.A ? "foo" : "bar";
+ }
+ }
+}
\ No newline at end of file