Repository: TypeScript
Issue: Consider deprecating namespaces declared with the `module`  keyword
Labels: Suggestion,In Discussion

# Background

Today, TypeScript has two uses of the `module` keyword.

The first is called an "ambient module declaration".

```ts
declare module "some-library" {
  // ...
}

declare module "*.css";
```

While we often prefer people author declaration files and submit them to DefinitelyTyped, the `declare module` syntax here is fine.

The second use is for *namespace* declarations.

```ts
module foo {}
declare module bar.baz {}
```

This is odd - these are called "namespace" declarations? Well, namespace declarations support using either the `namespace` keyword, or the `module` keyword. You could replace `module` with `namespace` in that last code snippet and it would work the same.

But why? Why support two ways to do the same thing? Because originally, TypeScript was designed with speculation that JavaScript would have two organizational schemes: "external modules" and "internal modules". External modules were files with isolated top-level scopes that could import/export values. Internal modules were named blocks of code that could export values.

Eventually, JavaScript just got "external modules" and called them "modules". TypeScript was left with two concepts and eventually it was too confusing. So in TypeScript 1.5, we introduced the `namespace` keyword to make the distinction clearer. Over time, the community preferred using the `namespace` keyword and linters discouraged the use of `module` in their place.

Recently, TC39 has been discussing two additions to JavaScript - [module expressions](https://github.com/tc39/proposal-module-expressions) and [module declarations](https://github.com/tc39/proposal-module-expressions). These proposals have some overlap with namespaces, but ultimately act different and enable different functionality. Regardless of whether we support the proposals or they go in, during discussion, most people were surprised that the use of `module` for namespaces wasn't at least deprecated.

As we discuss TypeScript 5.0, we're considering some cleanup in the flag and language space.

# Deprecation Proposal

In https://github.com/microsoft/TypeScript/issues/51813, we discussed the matter and felt comfortable with deprecating the use of the `module` keyword in namespace declarations. Deprecation plans are guided by plans discussed at https://github.com/microsoft/TypeScript/issues/51000.

What this would amount to is a graceful parse on any namespace declaration declared with `module`. In editor scenarios, our language service would provide a quick fix to replace that keyword with `namespace`. When `"ignoreDeprecations"": "5.0"` is turned on, we would still provide an editor suggestion which would enable the same quick fix.

## Caveats

This plan seems sound in *implementation files*; however, if a `module`-declared namespace appears in a declaration file from a 3rd party package, you're out of luck. At best, we could only error on implementation files.

So it's unclear if we'll be stuck with `module` keyword-declared namespaces in `.d.ts` files forever, or if this is possibly the first step in phasing that out too. Even if we wanted to support the module declarations proposal, it seems unclear whether we could when declaration files still contain `module` keyword-declared namespaces.

# Reconsideration

Here's a few points to consider:

* The work to deprecate is higher than the maintenance of the `module` keyword over the last 8 years. In fact, writing this deprecation plan was more work than that.
* Forcing namespace users off of `module` in implementation files seems fine, but it feels kind of pointless if we can't break them in declaration files.
* To some extent, erroring on a keyword that no new code uses anyway feels like a break for the sake of purity. It heavily favors conceptual cleanliness for implementers without much benefit for people using TypeScript.