-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider deprecating namespaces declared with the module
keyword
#51825
Comments
If |
Thank you for raising this! This looks like an excellent deprecation opportunity that will reduce the current confusion caused by having two ways to declare namespaces. Especially when it's clear cut that one keyword is preferred ( Experience in BloombergHere is some context on general namespace usage within the Bloomberg JS environment. This runtime approximates a pure ES modules-based environment which means no need to cater to CommonJS. Linting in Bloomberg’s environment ensures that namespaces are only permitted in declaration files and can only use the modern When one imposes linting restrictions on a developer community, it usually results in questions like "why am I not allowed to do that?" The internal feedback on these restrictions we've heard is:
The General Case for Removal(Let's ignore the specifics of what The main argument I would make here is that it's positive for the TypeScript ecosystem as a whole to minimize confusing relics. And it's positive for the JavaScript ecosystem to gain access to prime ergonomic syntax. Given the modern-day lack of enthusiasm for any kind of namespace usage, With any migration, it's all made easier by starting earlier, which means starting as soon as possible on the implementation files. With the current deprecation proposal, that will be around three years until full removal from implementation files. That sets the scene for the subsequent removal from declaration files once usage is low enough. Next Step SuggestionsAuto-Modernizing Declaration EmitToday compiling the TypeScript file To accelerate migration within the declaration file ecosystem, maybe we could immediately update TypeScript's declaration emitter to output modern syntax even if the implementation file continues to use the legacy syntax. DefinitelyTyped MigrationsThis could be a big topic all by itself. Given that there is some level of ecosystem centralization around DefinitelyTyped, can we seed trends there to assist declaration syntax migrations?
I'd like to hear more from DT experts on this. TelemetryAnother big topic. VS Code already implements opt-out remote reporting of TypeScript language server crash stacks today. The documentation says it also passes on some usage data. Maybe this could be expanded, in a very minimal anonymized way, to convey when usage of a legacy TypeScript feature has been detected. This would help provide confidence that the final removal from declaration files could proceed without impacting too many users. SummaryDeprecating and removing the legacy keyword usage seems like an excellent move and is highly appreciated. Whilst the keyword could be left around forever as a curiosity, taking proactive steps towards improving both the TypeScript and JavaScript languages helps all users and is the kind of healthy stewardship TypeScript is known for. |
@CC972 is about to start work on Auto-Modernizing Declaration Emit as described above supported by @dragomirtitian. |
I'm not a DT expert but have been working with DT folks recently on DefinitelyTyped/DefinitelyTyped#65993. The points you've suggested all sound very doable to me.
Yes: https://typescript-eslint.io/rules/prefer-namespace-keyword. The repo already has support for typescript-eslint rules. We can enable that rule in the repo and use the rule's auto-fixer.
Yes, and I'd be happy to help with that. One can imagine a script like: for repo in a b c; do
gh repo clone a
cd a
npx eslint . --config /path/to/just/prefer-namespace-keyword/config --fix
# git commands to create branch and send PR
cd ..
end |
My goodness. @JoshuaKGoldberg I reviewed your linked DT issue and you are not messing around. This is an excellent plan. Thank you for volunteering. If you need anything, please shout and I will arrange assistance. |
I started on DefinitelyTyped/DefinitelyTyped#66292. It was actually pretty quick. If you want me to apply the same fixing to any other repo, I can be shouted at here/anywhere and/or tagged an issue. (@robpalme I do love the idea of giving you an excuse to tell me to go do work 😄)
While the maintenance cost may be near-zero, the education cost is likely higher. I've found that I've had to repeatedly explain to learners why searches for "typescript modules" & similar terms end up with this old |
You are a good egg, Josh. Thanks for pushing this forwards. |
As a refresher on the current status:
|
After speaking with @RyanCavanaugh it seems like there may still be some concern about impacting active projects that want to upgrade TypeScript but also consume legacy DTS files. For example, where they vendored/snapshotted DTS files containing the old keyword from an unmaintained project. So what can we do now to keep things moving forwards? JSDoc offers the How about we do the same for the A built-in quickfix would be offered to convert this to |
I think we'd be okay with something that issues a language service deprecation diagnostic. I don't know if we really need the quick fix, but not opposed either. |
Background
Today, TypeScript has two uses of the
module
keyword.The first is called an "ambient module declaration".
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.
This is odd - these are called "namespace" declarations? Well, namespace declarations support using either the
namespace
keyword, or themodule
keyword. You could replacemodule
withnamespace
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 thenamespace
keyword and linters discouraged the use ofmodule
in their place.Recently, TC39 has been discussing two additions to JavaScript - module expressions and module declarations. 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 #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 #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 withnamespace
. 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 containmodule
keyword-declared namespaces.Reconsideration
Here's a few points to consider:
module
keyword over the last 8 years. In fact, writing this deprecation plan was more work than that.module
in implementation files seems fine, but it feels kind of pointless if we can't break them in declaration files.The text was updated successfully, but these errors were encountered: