Skip to content
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

ES Module imports discarded when they include a type and a side-effect #28285

Closed
KeithHenry opened this issue Nov 1, 2018 · 4 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@KeithHenry
Copy link

When an ES module syntax import has an explicit type and a side effect it is excluded from the output JS.

TypeScript Version: 3.2.0-dev.20181101

Search Terms:

  • ES Modules
  • Module resolution

Code

  • tsconfig.json target ESNext
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext"
  }
}
  • source-component.ts with an export and a side effect
export class SourceComponent extends HTMLElement {
    // Web component implementation   
}
customElements.define('source-component', SourceComponent);
  • missing-import.ts that references the dependency as a type and expects the side effect
import {SourceComponent} from './source-component.js';
const example = document.createElement('source-component') as SourceComponent;

Expected behaviour:

When output to missing-import.js the reference should be retained:

import {SourceComponent} from './source-component.js';
const example = document.createElement('source-component');

An import as a side effect would be acceptable too:

import './source-component.js';
const example = document.createElement('source-component');

Actual behaviour:

The import is stripped out:

const example = document.createElement('source-component');

Workaround:
Duplicate side effect import statements are retained:

import {SourceComponent} from './source-component.js';
import './source-component.js';
const example = document.createElement('source-component') as SourceComponent;
@weswigham
Copy link
Member

Duplicate of #9191 I imagine.

@weswigham weswigham added the Duplicate An existing issue was already created label Nov 1, 2018
@KeithHenry
Copy link
Author

@weswigham Certainly looks like it, only this is explicit ESNext modules and #9191 is referencing require - I assume that means a fix for require would be a fix for ESNext modules?

Only require is doing some mapping and ES Modules aren't - I think there's potentially a much easier fix for this as for ESNext modules in TS you have to include the .js suffix, so:

import { MyComponent } from './my-component'; // gets definition from my-component.d.ts
import { OtherComponent } from './other-component.js'; // doesn't need to check, always include in JS output

#9191 has been sitting round for years without a fix because finding out whether the reference includes a side effect is incredibly difficult.

However this could be fixed by adding a special case for ESNext when an explicit .js file extension is present.

As a fix for this wouldn't necessarily be a fix for #9191 does this still count as a duplicate? Especially as #9191 is never going to get fixed (require will get deprecated first) and ES Modules will become the standard?

@weswigham
Copy link
Member

Even if the import includes .js extension, we still look up an associated .d.ts file, and you might still only use the types from it. The presence of an extension doesn't change anything, really.

@KeithHenry
Copy link
Author

@weswigham yes, so for TS the extension is optional, but for JS missing the extension will throw an error. The only reason to include the extension in TS is because you want the import to work in the JS output, and in that case you always want to retain it.

Imports with explicit .js extensions should always be in the output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants