From 7cbbb7e307949b6a6867ba08b0a08ab704d161ea Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Sep 2025 23:33:52 +0000
Subject: [PATCH] Implement TypeScript 6.0 deprecation of module keyword for
namespaces
Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
---
src/compiler/checker.ts | 67 ++++++++++++++-----
src/compiler/diagnosticMessages.json | 12 ++--
.../moduleDeclarationDeprecated_error1.ts | 27 ++++++++
...eclarationDeprecated_ignoreDeprecations.ts | 31 +++++++++
...moduleDeclarationDeprecated_suggestion1.ts | 57 ++++++++--------
5 files changed, 145 insertions(+), 49 deletions(-)
create mode 100644 tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts
create mode 100644 tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 66742c94f05..3d7e84321a5 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -1132,13 +1132,15 @@ import {
walkUpBindingElementsAndPatterns,
walkUpOuterExpressions,
walkUpParenthesizedExpressions,
- walkUpParenthesizedTypes,
- walkUpParenthesizedTypesAndGetParentAndChild,
- WhileStatement,
- WideningContext,
- WithStatement,
- WriterContextOut,
- YieldExpression,
+ walkUpParenthesizedTypes,
+ walkUpParenthesizedTypesAndGetParentAndChild,
+ Version,
+ versionMajorMinor,
+ WhileStatement,
+ WideningContext,
+ WithStatement,
+ WriterContextOut,
+ YieldExpression,
} from "./_namespaces/ts.js";
import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js";
import * as performance from "./_namespaces/ts.performance.js";
@@ -47992,16 +47994,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
- if (isIdentifier(node.name)) {
- checkCollisionsForDeclarationName(node, node.name);
- if (!(node.flags & (NodeFlags.Namespace | NodeFlags.GlobalAugmentation))) {
- const sourceFile = getSourceFileOfNode(node);
- const pos = getNonModifierTokenPosOfNode(node);
- const span = getSpanOfTokenAtPosition(sourceFile, pos);
- suggestionDiagnostics.add(
- createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead),
- );
- }
+ if (isIdentifier(node.name)) {
+ checkCollisionsForDeclarationName(node, node.name);
+ if (!(node.flags & (NodeFlags.Namespace | NodeFlags.GlobalAugmentation))) {
+ const sourceFile = getSourceFileOfNode(node);
+ const pos = getNonModifierTokenPosOfNode(node);
+ const span = getSpanOfTokenAtPosition(sourceFile, pos);
+
+ // Check if we should generate an error (TS 6.0+) or suggestion (older versions)
+ const currentVersion = new Version(versionMajorMinor);
+ const errorVersion = new Version("6.0");
+ const shouldError = currentVersion.compareTo(errorVersion) >= Comparison.EqualTo;
+
+ // Check if ignoreDeprecations should suppress this error
+ let shouldSuppress = false;
+ if (shouldError && compilerOptions.ignoreDeprecations) {
+ // Only valid ignoreDeprecations values: "5.0" and "6.0"
+ if (compilerOptions.ignoreDeprecations === "6.0") {
+ shouldSuppress = true;
+ }
+ }
+
+ if (shouldError && !shouldSuppress) {
+ // In TypeScript 6.0+, this is an error unless suppressed by ignoreDeprecations
+ const errorDiagnostic = createFileDiagnostic(
+ sourceFile,
+ span.start,
+ span.length,
+ Diagnostics.The_module_keyword_is_not_allowed_for_namespace_declarations_Use_the_namespace_keyword_instead
+ );
+ diagnostics.add(errorDiagnostic);
+ } else {
+ // In older versions or when suppressed, keep as suggestion
+ const suggestionDiagnostic = createFileDiagnostic(
+ sourceFile,
+ span.start,
+ span.length,
+ Diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead
+ );
+ suggestionDiagnostics.add(suggestionDiagnostic);
+ }
+ }
}
checkExportsOnMergedDeclarations(node);
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 22ac200a0dc..d44e112cbbc 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -1820,10 +1820,14 @@
"category": "Error",
"code": 1539
},
- "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.": {
- "category": "Suggestion",
- "code": 1540,
- "reportsDeprecated": true
+ "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.": {
+ "category": "Suggestion",
+ "code": 1540,
+ "reportsDeprecated": true
+ },
+ "The 'module' keyword is not allowed for namespace declarations. Use the 'namespace' keyword instead.": {
+ "category": "Error",
+ "code": 1547
},
"Type-only import of an ECMAScript module from a CommonJS module must have a 'resolution-mode' attribute.": {
"category": "Error",
diff --git a/tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts b/tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts
new file mode 100644
index 00000000000..9c6a6315d20
--- /dev/null
+++ b/tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts
@@ -0,0 +1,27 @@
+///
+
+// @Filename: a.ts
+////[|module|] mod1 { export let x: number }
+////declare [|module|] mod2 { export let x: number }
+////export [|module|] mod3 { export let x: number }
+////export declare [|module|] mod4 { export let x: number }
+////namespace mod5 { export let x: number }
+////declare namespace mod6 { export let x: number }
+////mod1.x = 1;
+////mod2.x = 1;
+////mod5.x = 1;
+////mod6.x = 1;
+
+// @Filename: b.ts
+////declare module "global-ambient-module" {}
+
+goTo.file("a.ts")
+const errorDiagnostics = test.ranges().map(range => ({
+ code: 1547,
+ message: "The 'module' keyword is not allowed for namespace declarations. Use the 'namespace' keyword instead.",
+ range,
+}));
+verify.getSemanticDiagnostics(errorDiagnostics)
+
+goTo.file("b.ts")
+verify.getSemanticDiagnostics([])
\ No newline at end of file
diff --git a/tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts b/tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts
new file mode 100644
index 00000000000..6ca2f2d05e2
--- /dev/null
+++ b/tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts
@@ -0,0 +1,31 @@
+///
+
+// @ignoreDeprecations: 6.0
+// @Filename: a.ts
+////[|module|] mod1 { export let x: number }
+////declare [|module|] mod2 { export let x: number }
+////export [|module|] mod3 { export let x: number }
+////export declare [|module|] mod4 { export let x: number }
+////namespace mod5 { export let x: number }
+////declare namespace mod6 { export let x: number }
+////declare module "module-augmentation" {}
+////declare global {}
+////mod1.x = 1;
+////mod2.x = 1;
+////mod5.x = 1;
+////mod6.x = 1;
+
+// @Filename: b.ts
+////module "global-ambient-module" {}
+
+goTo.file("a.ts")
+const diagnostics = test.ranges().map(range => ({
+ code: 1540,
+ message: "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.",
+ reportsDeprecated: true as true,
+ range,
+}));
+verify.getSuggestionDiagnostics(diagnostics)
+
+goTo.file("b.ts")
+verify.getSuggestionDiagnostics([])
\ No newline at end of file
diff --git a/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts b/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts
index 5554300a5a0..96f34910f7d 100644
--- a/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts
+++ b/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts
@@ -1,30 +1,31 @@
-///
-// @Filename: a.ts
-////[|module|] mod1 { export let x: number }
-////declare [|module|] mod2 { export let x: number }
-////export [|module|] mod3 { export let x: number }
-////export declare [|module|] mod4 { export let x: number }
-////namespace mod5 { export let x: number }
-////declare namespace mod6 { export let x: number }
-////declare module "module-augmentation" {}
-////declare global {}
-////mod1.x = 1;
-////mod2.x = 1;
-////mod5.x = 1;
-////mod6.x = 1;
-
-// @Filename: b.ts
-////module "global-ambient-module" {}
-
-goTo.file("a.ts")
-const diagnostics = test.ranges().map(range => ({
- code: 1540,
- message: "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.",
- reportsDeprecated: true,
- range,
-}));
-verify.getSuggestionDiagnostics(diagnostics)
-
-goTo.file("b.ts")
+///
+// @ignoreDeprecations: 6.0
+// @Filename: a.ts
+////[|module|] mod1 { export let x: number }
+////declare [|module|] mod2 { export let x: number }
+////export [|module|] mod3 { export let x: number }
+////export declare [|module|] mod4 { export let x: number }
+////namespace mod5 { export let x: number }
+////declare namespace mod6 { export let x: number }
+////declare module "module-augmentation" {}
+////declare global {}
+////mod1.x = 1;
+////mod2.x = 1;
+////mod5.x = 1;
+////mod6.x = 1;
+
+// @Filename: b.ts
+////module "global-ambient-module" {}
+
+goTo.file("a.ts")
+const diagnostics = test.ranges().map(range => ({
+ code: 1540,
+ message: "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.",
+ reportsDeprecated: true as true,
+ range,
+}));
+verify.getSuggestionDiagnostics(diagnostics)
+
+goTo.file("b.ts")
verify.getSuggestionDiagnostics([])