Skip to content

Allow type-only imports on ImportEqualsDeclarations #41573

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

Merged

Conversation

andrewbranch
Copy link
Member

@andrewbranch andrewbranch commented Nov 17, 2020

A while back, @gr2m asked me to help take a look at octokit/webhooks.js#245. My summary of the issue is:

  1. @octokit/webhooks.js legitimately targets --module=es2015 because it ships ESM to npm
  2. Naturally, it also generates type declarations with --declaration
  3. It has a CommonJS dependency, "aggregate-error"

The combination of (1) and (3) is a problem—CommonJS imports are not allowed with --module=es2015. The error message says that you have to turn on allowSyntheticDefaultImports or esModuleInterop, which is what the Octokit maintainers did. However, that is a problem for (2), because it just pushes the error onto consumers of the library who don’t have esModuleInterop turned on (although it is suppressible with skipLibCheck).

In places where they used AggregateError without it making its way into the generated type declarations, they were able to turn esModuleInterop off, continue using a default import (since it works at runtime—this kind of interop is in the current ESM draft spec, and is implemented in Node now), and suppress the TypeScript error with // @ts-ignore. However, there was one place where they needed to declare a publicly exposed class that extended AggregateError as part of its definition. They ended up simply copying the relevant parts of the class declaration as they had no good, portable way to import it. (An ImportTypeNode wouldn’t have worked without separately declaring a value side for the constructor, although this might have been slightly less tedious than copying the declaration.) If the syntax import type AggregateError = require("aggregate-error") had been allowed, it would have been a perfect fit—it captures both the type and the value side of the AggregateError class, and would have been allowed in the extends clause because the class declaration was ambient. The CJS-style import can be allowed to exist even in --module=es2015 because it will necessarily be elided due to the type keyword.

All the type-checking (and parsing—in order to give a good parse error) mechanics were already enabled for this, so this PR mostly just removes error messages to allow it. It’s obviously not a full solution to the awkward interop story between ESM and CJS, but it’s an additional tool that library authors can use, at next to no implementation cost. The only downside here is the factory API change for ImportEqualsDeclaration. (I could improve back-compat by putting the isTypeOnly parameter last, but it breaks the pattern of node factory function parameters corresponding to syntax order—i.e., the type keyword comes before the name identifier when written out, so the isTypeOnly parameter comes before the name parameter in the factory function.)

Also fixes #41603

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch
Copy link
Member

@DanielRosenwasser DanielRosenwasser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but let's chat about it at a design meeting.

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch
@DanielRosenwasser
Copy link
Member

Could you also add tests with importsNotUsedAsValues?

Copy link
Member

@DanielRosenwasser DanielRosenwasser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests for importsNotUsedAsValues

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch
@andrewbranch
Copy link
Member Author

All I want is just once to be able to push a change that will pass CI without having run tests locally, just once

@DanielRosenwasser
Copy link
Member

Sounds like this is useful enough for us that we don't need a bot action: #39898

@DanielRosenwasser
Copy link
Member

Aw you use your own fork, sad!

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@typescript-bot typescript-bot added For Milestone Bug PRs that fix a bug with a specific milestone and removed For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Dec 3, 2020

Verified

This commit was signed with the committer’s verified signature. The key has expired.
andrewbranch Andrew Branch
@andrewbranch andrewbranch force-pushed the feature/type-only-cjs-import branch from f7f9e81 to e7c5798 Compare December 3, 2020 19:37
@andrewbranch andrewbranch merged commit 69bc3f3 into microsoft:master Dec 3, 2020
@andrewbranch andrewbranch deleted the feature/type-only-cjs-import branch December 3, 2020 21:27
Kingwl pushed a commit to Kingwl/TypeScript that referenced this pull request Dec 4, 2020
* Allow type-only ImportEqualsDeclarations

* Suppress CJS-in-ESM error when type-only

* Add grammar error on import type in import alias

* Update API baselines

* Fix importsNotUsedAsValues with ImportEqualsDeclarations

* Make bad error talk words more good for Daniel. Fixes microsoft#41603

* One more error message baseline update

* Update transformer and emitter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug PRs that fix a bug with a specific milestone
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Missing or extra word in error message
4 participants