Repository navigation
error importing type from esm in commonjsΒ #47338
Copy link
Copy link
Closed
Labels
Fix AvailableA PR has been opened for this issueA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
Milestone
Description
Bug Report
π Search Terms
typeof import
import esm type from commonjs module
node12 nodenext
π Version & Regression Information
- I was unable to test this on prior versions because
"module": "node12"only works intypescript@next
β― Playground Link
I was unable to find a way to emulate "type": "commonjs" in package.json on typescript playground
here is a repo that can be used to reproduce this error
https://github.com/nstringham/min-to-reproduce-typescript-import-problem
π» Code
{
"compilerOptions": {
"module": "nodenext"
}
}export type Color = "red" | "green" | "blue";
export function printColor(color: Color): void;import type { Color } from "dependency";
const myColor: Color = "blue";
const myOtherColor: import("dependency").Color = "red";
async function main() {
const { printColor } = await import("dependency");
printColor(myColor);
printColor(myOtherColor);
}
main();π Actual behavior
code compiles correctly but displays the following error
index.ts:1:28 - error TS1471: Module 'dependency' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
1 import type { Color } from "dependency";
~~~~~~~~~~~~
index.ts:5:28 - error TS1471: Module 'dependency' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
5 const myOtherColor: import("dependency").Color = "red";
~~~~~~~~~~~~
π Expected behavior
code compiles correctly with no errors
βͺοΈ Workaround
because typescript compiles correctly despite errors this error can be ignored with // @ts-ignore
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Fix AvailableA PR has been opened for this issueA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
Activity
weswigham commentedon Jan 18, 2022
So, my thoughts on this, since there have been a few issues in this vein (eg, #47248) and while I've spoken to them in team settings, I have yet to set them down.
This is technically working as expected right now, since you're importing an esm format files from a cjs one using constructs that check runtime behavior. You may think, "But Wesley Wigham (@weswigham), I'm only importing the types, surely that means it's safe to just give me the type data, right!?!? There's no runtime to be concerned about!" And you'd be right, but only in the narrowest sense - if we were to allow pulling types from modules whose format is incompatible like this, it becomes a breaking change to then add a compatible format to that package, rather than a non-breaking one. Meaning we'd be making adding more format compatibility via conditional
exportsa breaking change, which defeats a core premise of conditional exports.Therefore, I would not expect us to ever make the above work as written; instead, I would anticipate us adding a syntax to specifically get the esm or cjs format type information for a specifier even when that's not the default mode for the file's imports (like how you have dynamic import available in a cjs context to do esm resolution). Something like
import("dependency", { assert: { mode: "esm" } }).Color,import type { Color } from "dependency" assert { mode: "esm" }or similar. Incredibly verbose, but one of the only ways I can think to do it without inadvertently introducing refactoring hazards or introducing bespoke syntax.nstringham commentedon Jan 18, 2022
makes sense. Thanks for looking into it