Skip to content

Commit ed79345

Browse files
frigus02c0sta
authored andcommitted
isolatedModules error on global shadowed by imported type (microsoft#56732)
1 parent 18f5d3f commit ed79345

6 files changed

+270
-0
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ import {
735735
isTypeNode,
736736
isTypeNodeKind,
737737
isTypeOfExpression,
738+
isTypeOnlyImportDeclaration,
738739
isTypeOnlyImportOrExportDeclaration,
739740
isTypeOperatorNode,
740741
isTypeParameterDeclaration,
@@ -3603,6 +3604,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36033604
);
36043605
}
36053606
}
3607+
3608+
// Look at 'compilerOptions.isolatedModules' and not 'getIsolatedModules(...)' (which considers 'verbatimModuleSyntax')
3609+
// here because 'verbatimModuleSyntax' will already have an error for importing a type without 'import type'.
3610+
if (compilerOptions.isolatedModules && result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value) {
3611+
const isGlobal = lookup(globals, name, meaning) === result;
3612+
const nonValueSymbol = isGlobal && isSourceFile(lastLocation!) && lastLocation.locals && lookup(lastLocation.locals, name, ~SymbolFlags.Value);
3613+
if (nonValueSymbol) {
3614+
const importDecl = nonValueSymbol.declarations?.find(d => d.kind === SyntaxKind.ImportSpecifier || d.kind === SyntaxKind.ImportClause || d.kind === SyntaxKind.NamespaceImport || d.kind === SyntaxKind.ImportEqualsDeclaration);
3615+
if (importDecl && !isTypeOnlyImportDeclaration(importDecl)) {
3616+
error(importDecl, Diagnostics.Import_0_conflicts_with_global_value_used_in_this_file_so_must_be_declared_with_a_type_only_import_when_isolatedModules_is_enabled, unescapeLeadingUnderscores(name));
3617+
}
3618+
}
3619+
}
36063620
});
36073621
}
36083622
return result;

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3731,6 +3731,10 @@
37313731
"category": "Error",
37323732
"code": 2865
37333733
},
3734+
"Import '{0}' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.": {
3735+
"category": "Error",
3736+
"code": 2866
3737+
},
37343738

37353739
"Import declaration '{0}' is using private name '{1}'.": {
37363740
"category": "Error",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
bad.ts(1,10): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
2+
bad.ts(1,10): error TS1484: 'Date' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
3+
bad.ts(1,16): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
4+
bad.ts(1,16): error TS1484: 'Event' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
5+
good.ts(2,10): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
6+
7+
8+
==== ./types.ts (0 errors) ====
9+
export interface Date {
10+
day: number;
11+
month: number;
12+
year: number;
13+
}
14+
15+
export namespace Event {
16+
export type T = any;
17+
}
18+
19+
==== ./node.d.ts (0 errors) ====
20+
declare module 'node:console' {
21+
global {
22+
interface Console {
23+
Console: console.ConsoleConstructor;
24+
}
25+
namespace console {
26+
interface ConsoleConstructor {
27+
prototype: Console;
28+
new (): Console;
29+
}
30+
}
31+
var console: Console;
32+
}
33+
export = globalThis.console;
34+
}
35+
36+
==== ./bad.ts (4 errors) ====
37+
import { Date, Event } from './types';
38+
~~~~
39+
!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
40+
~~~~
41+
!!! error TS1484: 'Date' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
42+
~~~~~
43+
!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
44+
~~~~~
45+
!!! error TS1484: 'Event' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
46+
function foo(a: Date) {
47+
const b = new Date(a.year, a.month, a.day);
48+
return b.getTime();
49+
}
50+
function bar() {
51+
return new Event('bar') as Event.T;
52+
}
53+
54+
==== ./good.ts (1 errors) ====
55+
import type { Date, Event } from './types';
56+
import { Console } from 'node:console';
57+
~~~~~~~
58+
!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
59+
function foo(a: Date) {
60+
const b = new Date(a.year, a.month, a.day);
61+
return b.getTime();
62+
}
63+
function bar() {
64+
return new Event('bar') as Event.T;
65+
}
66+
const baz: Console = new Console();
67+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
bad.ts(1,10): error TS2866: Import 'Date' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
2+
bad.ts(1,16): error TS2866: Import 'Event' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
3+
4+
5+
==== ./types.ts (0 errors) ====
6+
export interface Date {
7+
day: number;
8+
month: number;
9+
year: number;
10+
}
11+
12+
export namespace Event {
13+
export type T = any;
14+
}
15+
16+
==== ./node.d.ts (0 errors) ====
17+
declare module 'node:console' {
18+
global {
19+
interface Console {
20+
Console: console.ConsoleConstructor;
21+
}
22+
namespace console {
23+
interface ConsoleConstructor {
24+
prototype: Console;
25+
new (): Console;
26+
}
27+
}
28+
var console: Console;
29+
}
30+
export = globalThis.console;
31+
}
32+
33+
==== ./bad.ts (2 errors) ====
34+
import { Date, Event } from './types';
35+
~~~~
36+
!!! error TS2866: Import 'Date' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
37+
~~~~~
38+
!!! error TS2866: Import 'Event' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
39+
function foo(a: Date) {
40+
const b = new Date(a.year, a.month, a.day);
41+
return b.getTime();
42+
}
43+
function bar() {
44+
return new Event('bar') as Event.T;
45+
}
46+
47+
==== ./good.ts (0 errors) ====
48+
import type { Date, Event } from './types';
49+
import { Console } from 'node:console';
50+
function foo(a: Date) {
51+
const b = new Date(a.year, a.month, a.day);
52+
return b.getTime();
53+
}
54+
function bar() {
55+
return new Event('bar') as Event.T;
56+
}
57+
const baz: Console = new Console();
58+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
bad.ts(1,10): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
2+
bad.ts(1,10): error TS1484: 'Date' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
3+
bad.ts(1,10): error TS2866: Import 'Date' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
4+
bad.ts(1,16): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
5+
bad.ts(1,16): error TS1484: 'Event' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
6+
bad.ts(1,16): error TS2866: Import 'Event' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
7+
good.ts(2,10): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
8+
9+
10+
==== ./types.ts (0 errors) ====
11+
export interface Date {
12+
day: number;
13+
month: number;
14+
year: number;
15+
}
16+
17+
export namespace Event {
18+
export type T = any;
19+
}
20+
21+
==== ./node.d.ts (0 errors) ====
22+
declare module 'node:console' {
23+
global {
24+
interface Console {
25+
Console: console.ConsoleConstructor;
26+
}
27+
namespace console {
28+
interface ConsoleConstructor {
29+
prototype: Console;
30+
new (): Console;
31+
}
32+
}
33+
var console: Console;
34+
}
35+
export = globalThis.console;
36+
}
37+
38+
==== ./bad.ts (6 errors) ====
39+
import { Date, Event } from './types';
40+
~~~~
41+
!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
42+
~~~~
43+
!!! error TS1484: 'Date' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
44+
~~~~
45+
!!! error TS2866: Import 'Date' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
46+
~~~~~
47+
!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
48+
~~~~~
49+
!!! error TS1484: 'Event' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
50+
~~~~~
51+
!!! error TS2866: Import 'Event' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled.
52+
function foo(a: Date) {
53+
const b = new Date(a.year, a.month, a.day);
54+
return b.getTime();
55+
}
56+
function bar() {
57+
return new Event('bar') as Event.T;
58+
}
59+
60+
==== ./good.ts (1 errors) ====
61+
import type { Date, Event } from './types';
62+
import { Console } from 'node:console';
63+
~~~~~~~
64+
!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
65+
function foo(a: Date) {
66+
const b = new Date(a.year, a.month, a.day);
67+
return b.getTime();
68+
}
69+
function bar() {
70+
return new Event('bar') as Event.T;
71+
}
72+
const baz: Console = new Console();
73+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// @isolatedModules: false, true
2+
// @verbatimModuleSyntax: false, true
3+
// @noEmit: true
4+
// @noTypesAndSymbols: true
5+
6+
// @filename: ./types.ts
7+
export interface Date {
8+
day: number;
9+
month: number;
10+
year: number;
11+
}
12+
13+
export namespace Event {
14+
export type T = any;
15+
}
16+
17+
// @filename: ./node.d.ts
18+
declare module 'node:console' {
19+
global {
20+
interface Console {
21+
Console: console.ConsoleConstructor;
22+
}
23+
namespace console {
24+
interface ConsoleConstructor {
25+
prototype: Console;
26+
new (): Console;
27+
}
28+
}
29+
var console: Console;
30+
}
31+
export = globalThis.console;
32+
}
33+
34+
// @filename: ./bad.ts
35+
import { Date, Event } from './types';
36+
function foo(a: Date) {
37+
const b = new Date(a.year, a.month, a.day);
38+
return b.getTime();
39+
}
40+
function bar() {
41+
return new Event('bar') as Event.T;
42+
}
43+
44+
// @filename: ./good.ts
45+
import type { Date, Event } from './types';
46+
import { Console } from 'node:console';
47+
function foo(a: Date) {
48+
const b = new Date(a.year, a.month, a.day);
49+
return b.getTime();
50+
}
51+
function bar() {
52+
return new Event('bar') as Event.T;
53+
}
54+
const baz: Console = new Console();

0 commit comments

Comments
 (0)