diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4a294a2474f26..0e7a89111164d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -45427,6 +45427,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; error(node, message, symbolToString(symbol)); } + else if (node.kind !== SyntaxKind.ExportSpecifier) { + // Look at 'compilerOptions.isolatedModules' and not 'getIsolatedModules(...)' (which considers 'verbatimModuleSyntax') + // here because 'verbatimModuleSyntax' will already have an error for importing a type without 'import type'. + const appearsValueyToTranspiler = compilerOptions.isolatedModules && !findAncestor(node, isTypeOnlyImportOrExportDeclaration); + if (appearsValueyToTranspiler && symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue)) { + error( + node, + Diagnostics.Import_0_conflicts_with_local_value_so_must_be_declared_with_a_type_only_import_when_isolatedModules_is_enabled, + symbolToString(symbol), + isolatedModulesLikeFlagName, + ); + } + } if ( getIsolatedModules(compilerOptions) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 81fd5981ac8a4..7ba864791bd35 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3711,6 +3711,10 @@ "category": "Error", "code": 2864 }, + "Import '{0}' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled.": { + "category": "Error", + "code": 2865 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index d287bec994046..b3c86f6390ff8 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -140,6 +140,7 @@ class CompilerTest { "importHelpers", "downlevelIteration", "isolatedModules", + "verbatimModuleSyntax", "strict", "noImplicitAny", "strictNullChecks", diff --git a/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=false,verbatimmodulesyntax=true).errors.txt b/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=false,verbatimmodulesyntax=true).errors.txt new file mode 100644 index 0000000000000..6d699b7aaea0b --- /dev/null +++ b/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=false,verbatimmodulesyntax=true).errors.txt @@ -0,0 +1,19 @@ +bad.ts(1,10): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled. +bad.ts(1,10): error TS1484: 'FC' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled. + + +==== types.ts (0 errors) ==== + export type FC = () => void; + +==== bad.ts (2 errors) ==== + import { FC } from "./types"; + ~~ +!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled. + ~~ +!!! error TS1484: 'FC' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled. + let FC: FC | null = null; + +==== good.ts (0 errors) ==== + import type { FC } from "./types"; + let FC: FC | null = null; + \ No newline at end of file diff --git a/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=true,verbatimmodulesyntax=false).errors.txt b/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=true,verbatimmodulesyntax=false).errors.txt new file mode 100644 index 0000000000000..04875f8fca464 --- /dev/null +++ b/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=true,verbatimmodulesyntax=false).errors.txt @@ -0,0 +1,16 @@ +bad.ts(1,10): error TS2865: Import 'FC' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled. + + +==== types.ts (0 errors) ==== + export type FC = () => void; + +==== bad.ts (1 errors) ==== + import { FC } from "./types"; + ~~ +!!! error TS2865: Import 'FC' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled. + let FC: FC | null = null; + +==== good.ts (0 errors) ==== + import type { FC } from "./types"; + let FC: FC | null = null; + \ No newline at end of file diff --git a/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=true,verbatimmodulesyntax=true).errors.txt b/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=true,verbatimmodulesyntax=true).errors.txt new file mode 100644 index 0000000000000..f87ec7ea8fc17 --- /dev/null +++ b/tests/baselines/reference/isolatedModulesSketchyAliasLocalMerge(isolatedmodules=true,verbatimmodulesyntax=true).errors.txt @@ -0,0 +1,22 @@ +bad.ts(1,10): error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled. +bad.ts(1,10): error TS1484: 'FC' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled. +bad.ts(1,10): error TS2865: Import 'FC' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled. + + +==== types.ts (0 errors) ==== + export type FC = () => void; + +==== bad.ts (3 errors) ==== + import { FC } from "./types"; + ~~ +!!! error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled. + ~~ +!!! error TS1484: 'FC' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled. + ~~ +!!! error TS2865: Import 'FC' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled. + let FC: FC | null = null; + +==== good.ts (0 errors) ==== + import type { FC } from "./types"; + let FC: FC | null = null; + \ No newline at end of file diff --git a/tests/cases/compiler/isolatedModulesSketchyAliasLocalMerge.ts b/tests/cases/compiler/isolatedModulesSketchyAliasLocalMerge.ts new file mode 100644 index 0000000000000..fa5869c0da1c6 --- /dev/null +++ b/tests/cases/compiler/isolatedModulesSketchyAliasLocalMerge.ts @@ -0,0 +1,15 @@ +// @isolatedModules: false, true +// @verbatimModuleSyntax: false, true +// @noEmit: true +// @noTypesAndSymbols: true + +// @Filename: types.ts +export type FC = () => void; + +// @Filename: bad.ts +import { FC } from "./types"; +let FC: FC | null = null; + +// @Filename: good.ts +import type { FC } from "./types"; +let FC: FC | null = null;