Fix import= something type only from a module

This commit is contained in:
Andrew Branch committed 2020-01-28 14:53:00 -08:00
1 parent 7e1382aa1a
commit 419dba1714
12 files changed
+397 -12

No files matched your search

+26 -10
View File
@@ -2182,7 +2182,12 @@ namespace ts {
function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration, dontResolveAlias: boolean): Symbol | undefined {
if (node.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
return resolveExternalModuleSymbol(resolveExternalModuleName(node, getExternalModuleImportEqualsDeclarationExpression(node)));
const immediate = resolveExternalModuleName(node, getExternalModuleImportEqualsDeclarationExpression(node));
const resolved = resolveExternalModuleSymbol(immediate);
if (!markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, immediate)) {
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, resolved);
}
return resolved;
}
return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, dontResolveAlias);
}
@@ -2278,7 +2283,9 @@ namespace ts {
else if (hasSyntheticDefault) {
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
if (!isTypeOnly) markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, resolved);
if (!isTypeOnly && !markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, moduleSymbol)) {
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, resolved);
}
return resolved;
}
if (!isTypeOnly) markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, exportDefaultSymbol);
@@ -2289,8 +2296,11 @@ namespace ts {
function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined {
const moduleSpecifier = node.parent.parent.moduleSpecifier;
const isTypeOnly = markSymbolOfAliasDeclarationIfTypeOnly(node);
const resolved = resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
if (!isTypeOnly) markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, resolved);
const immediate = resolveExternalModuleName(node, moduleSpecifier);
const resolved = resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
if (!isTypeOnly && !markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, immediate)) {
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, resolved);
}
return resolved;
}
@@ -2459,7 +2469,9 @@ namespace ts {
function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined {
const expression = (isExportAssignment(node) ? node.expression : node.right) as EntityNameExpression | ClassExpression;
return getTargetOfAliasLikeExpression(expression, dontResolveAlias);
const resolved = getTargetOfAliasLikeExpression(expression, dontResolveAlias);
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(node, resolved);
return resolved;
}
function getTargetOfAliasLikeExpression(expression: Expression, dontResolveAlias: boolean) {
@@ -2556,14 +2568,18 @@ namespace ts {
return links.target;
}
function markSymbolOfAliasDeclarationIfResolvesToTypeOnly(aliasDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, resolvesToSymbol: Symbol | undefined) {
if (!aliasDeclaration || !resolvesToSymbol) return;
function markSymbolOfAliasDeclarationIfResolvesToTypeOnly(aliasDeclaration: Declaration | undefined, resolvesToSymbol: Symbol | undefined): boolean {
if (!aliasDeclaration || !resolvesToSymbol) return false;
const sourceSymbol = getSymbolOfNode(aliasDeclaration);
const links = getSymbolLinks(sourceSymbol);
if (links.typeOnlyDeclaration === undefined) {
resolvesToSymbol = resolvesToSymbol.exports?.get(InternalSymbolName.ExportEquals) ?? resolvesToSymbol;
const typeOnly = find(resolvesToSymbol.declarations, isTypeOnlyImportOrExportDeclaration);
links.typeOnlyDeclaration = typeOnly ?? getSymbolLinks(resolvesToSymbol).typeOnlyDeclaration ?? false;
const decl = typeOnly ?? getSymbolLinks(resolvesToSymbol).typeOnlyDeclaration ?? false;
links.typeOnlyDeclaration = decl;
return !!decl;
}
return false;
}
function markSymbolOfAliasDeclarationIfTypeOnly(aliasDeclaration: TypeOnlyCompatibleAliasDeclaration): boolean {
@@ -2711,8 +2727,8 @@ namespace ts {
throw Debug.assertNever(name, "Unknown entity name kind.");
}
Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
if (isIdentifier(name) && symbol.flags & SymbolFlags.Alias) {
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(getTypeOnlyCompatibleAliasDeclarationFromName(name), symbol);
if (isIdentifier(name) && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment)) {
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(getAliasDeclarationFromName(name), symbol);
}
return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol);
}
+3 -2
View File
@@ -2766,13 +2766,14 @@ namespace ts {
node.kind === SyntaxKind.PropertyAssignment && isAliasableExpression((node as PropertyAssignment).initializer);
}
export function getTypeOnlyCompatibleAliasDeclarationFromName(node: Identifier): TypeOnlyCompatibleAliasDeclaration | undefined {
export function getAliasDeclarationFromName(node: Identifier): Declaration | undefined {
switch (node.parent.kind) {
case SyntaxKind.ImportClause:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ExportSpecifier:
return node.parent as TypeOnlyCompatibleAliasDeclaration;
case SyntaxKind.ExportAssignment:
return node.parent as Declaration;
}
}
@@ -0,0 +1,45 @@
/d.ts(2,5): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
/e.ts(2,5): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
/f.ts(2,5): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
/g.ts(2,5): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
==== /a.ts (0 errors) ====
export class A {}
==== /b.ts (0 errors) ====
import type * as types from './a';
export = types; // Error
==== /c.ts (0 errors) ====
import * as types from './a';
export = types;
==== /d.ts (1 errors) ====
import types from './b';
new types.A(); // Error
~~~~~
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:13: 'types' was imported here.
==== /e.ts (1 errors) ====
import types = require('./b');
new types.A(); // Error
~~~~~
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:13: 'types' was imported here.
==== /f.ts (1 errors) ====
import * as types from './b';
new types.A(); // Error
~~~~~
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:13: 'types' was imported here.
==== /g.ts (1 errors) ====
import type types from './c'
new types.A(); // Error
~~~~~
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /g.ts:1:8: 'types' was imported here.
@@ -0,0 +1,69 @@
//// [tests/cases/conformance/externalModules/typeOnly/importEquals1.ts] ////
//// [a.ts]
export class A {}
//// [b.ts]
import type * as types from './a';
export = types; // Error
//// [c.ts]
import * as types from './a';
export = types;
//// [d.ts]
import types from './b';
new types.A(); // Error
//// [e.ts]
import types = require('./b');
new types.A(); // Error
//// [f.ts]
import * as types from './b';
new types.A(); // Error
//// [g.ts]
import type types from './c'
new types.A(); // Error
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
exports.A = A;
//// [b.js]
"use strict";
module.exports = types;
//// [c.js]
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var types = __importStar(require("./a"));
module.exports = types;
//// [d.js]
"use strict";
exports.__esModule = true;
new types.A(); // Error
//// [e.js]
"use strict";
exports.__esModule = true;
new types.A(); // Error
//// [f.js]
"use strict";
exports.__esModule = true;
new types.A(); // Error
//// [g.js]
"use strict";
exports.__esModule = true;
new types.A(); // Error
@@ -0,0 +1,54 @@
=== /a.ts ===
export class A {}
>A : Symbol(A, Decl(a.ts, 0, 0))
=== /b.ts ===
import type * as types from './a';
>types : Symbol(types, Decl(b.ts, 0, 11))
export = types; // Error
>types : Symbol(types, Decl(b.ts, 0, 11))
=== /c.ts ===
import * as types from './a';
>types : Symbol(types, Decl(c.ts, 0, 6))
export = types;
>types : Symbol(types, Decl(c.ts, 0, 6))
=== /d.ts ===
import types from './b';
>types : Symbol(types, Decl(d.ts, 0, 6))
new types.A(); // Error
>types.A : Symbol(types.A, Decl(a.ts, 0, 0))
>types : Symbol(types, Decl(d.ts, 0, 6))
>A : Symbol(types.A, Decl(a.ts, 0, 0))
=== /e.ts ===
import types = require('./b');
>types : Symbol(types, Decl(e.ts, 0, 0))
new types.A(); // Error
>types.A : Symbol(types.A, Decl(a.ts, 0, 0))
>types : Symbol(types, Decl(e.ts, 0, 0))
>A : Symbol(types.A, Decl(a.ts, 0, 0))
=== /f.ts ===
import * as types from './b';
>types : Symbol(types, Decl(f.ts, 0, 6))
new types.A(); // Error
>types.A : Symbol(types.A, Decl(a.ts, 0, 0))
>types : Symbol(types, Decl(f.ts, 0, 6))
>A : Symbol(types.A, Decl(a.ts, 0, 0))
=== /g.ts ===
import type types from './c'
>types : Symbol(types, Decl(g.ts, 0, 6))
new types.A(); // Error
>types.A : Symbol(types.A, Decl(a.ts, 0, 0))
>types : Symbol(types, Decl(g.ts, 0, 6))
>A : Symbol(types.A, Decl(a.ts, 0, 0))
@@ -0,0 +1,58 @@
=== /a.ts ===
export class A {}
>A : A
=== /b.ts ===
import type * as types from './a';
>types : typeof types
export = types; // Error
>types : typeof types
=== /c.ts ===
import * as types from './a';
>types : typeof types
export = types;
>types : typeof types
=== /d.ts ===
import types from './b';
>types : typeof types
new types.A(); // Error
>new types.A() : types.A
>types.A : typeof types.A
>types : typeof types
>A : typeof types.A
=== /e.ts ===
import types = require('./b');
>types : typeof types
new types.A(); // Error
>new types.A() : types.A
>types.A : typeof types.A
>types : typeof types
>A : typeof types.A
=== /f.ts ===
import * as types from './b';
>types : typeof types
new types.A(); // Error
>new types.A() : types.A
>types.A : typeof types.A
>types : typeof types
>A : typeof types.A
=== /g.ts ===
import type types from './c'
>types : any
new types.A(); // Error
>new types.A() : types.A
>types.A : typeof types.A
>types : typeof types
>A : typeof types.A
@@ -0,0 +1,17 @@
/c.ts(2,7): error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
==== /c.ts (1 errors) ====
import a = require('./b');
new a.A(); // Error
~
!!! error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
==== /a.ts (0 errors) ====
class A {}
export type { A }
==== /b.ts (0 errors) ====
import * as a from './a';
export = a;
@@ -0,0 +1,39 @@
//// [tests/cases/conformance/externalModules/typeOnly/importEquals2.ts] ////
//// [a.ts]
class A {}
export type { A }
//// [b.ts]
import * as a from './a';
export = a;
//// [c.ts]
import a = require('./b');
new a.A(); // Error
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
//// [b.js]
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var a = __importStar(require("./a"));
module.exports = a;
//// [c.js]
"use strict";
exports.__esModule = true;
var a = require("./b");
new a.A(); // Error
@@ -0,0 +1,21 @@
=== /c.ts ===
import a = require('./b');
>a : Symbol(a, Decl(c.ts, 0, 0))
new a.A(); // Error
>a : Symbol(a, Decl(c.ts, 0, 0))
=== /a.ts ===
class A {}
>A : Symbol(A, Decl(a.ts, 0, 0))
export type { A }
>A : Symbol(A, Decl(a.ts, 1, 13))
=== /b.ts ===
import * as a from './a';
>a : Symbol(a, Decl(b.ts, 0, 6))
export = a;
>a : Symbol(a, Decl(b.ts, 0, 6))
@@ -0,0 +1,24 @@
=== /c.ts ===
import a = require('./b');
>a : typeof a
new a.A(); // Error
>new a.A() : any
>a.A : any
>a : typeof a
>A : any
=== /a.ts ===
class A {}
>A : A
export type { A }
>A : A
=== /b.ts ===
import * as a from './a';
>a : typeof a
export = a;
>a : typeof a
@@ -0,0 +1,28 @@
// @esModuleInterop: true
// @Filename: /a.ts
export class A {}
// @Filename: /b.ts
import type * as types from './a';
export = types; // Error
// @Filename: /c.ts
import * as types from './a';
export = types;
// @Filename: /d.ts
import types from './b';
new types.A(); // Error
// @Filename: /e.ts
import types = require('./b');
new types.A(); // Error
// @Filename: /f.ts
import * as types from './b';
new types.A(); // Error
// @Filename: /g.ts
import type types from './c'
new types.A(); // Error
@@ -0,0 +1,13 @@
// @esModuleInterop: true
// @Filename: /a.ts
class A {}
export type { A }
// @Filename: /b.ts
import * as a from './a';
export = a;
// @Filename: /c.ts
import a = require('./b');
new a.A(); // Error