Repository navigation
Allow ES Module Type-Only Imports from CJS Modules #49721
Description
Activity
RyanCavanaugh commented
on Jun 30, 2022 MemberMore actionsPreviously discussed at #47338 (comment) - this not working is intentional since it's a forward-compat hazard.
The proposed solution at the time was to add import mode assertions, but people didn't like this (see comments #48644) and we couldn't agree on a different syntax that was acceptable, so moved import mode assertions to be nightly-only. There's issue #49055 tracking next steps on this issue.
Reacted by Thomas Hufschmidt- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.
on Jun 30, 2022 Workaround: https://www.npmjs.com/package/@brillout/import.
Not sure to understand why it doesn't, but for me just adding
// @ts-expect-erroris a good enough workaround to make my program typesafe without complicating things too much.// @ts-expect-error import type { ContainerDirective } from "mdast-util-directive";
Reacted by stooboo, Bradley Nelson, Armano, DiscreteTom, szacskesz, Nico Jansen, Andrzej Wódkiewicz and Parsa ShamaeezadehIn my case (building the Docusaurus framework packages), using
// @ts-expect-erroris not a good solution when those types are re-exported.The emitted
.d.tsfiles contain the imports but// @ts-expect-erroris not in the.d.tsoutput of the lib.This makes the framework users have compilation errors with
skipLibCheck: false, such as:../packages/docusaurus-mdx-loader/lib/loader.d.ts:9:32 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("unified")' call instead. 9 import type { Pluggable } from 'unified';
As far as I understand, Import attributes moved to stage 3 again with a new syntax (#53656)
See also #53426 (comment)
Do you think the following will fix the problem?
import type { Plugin } from 'unified' with { "resolution-mode": "import" };
Can we expect it to be available soon Ryan Cavanaugh (@RyanCavanaugh) ?
Looks like you'd rather not rush things according to this comment: #53656 (comment)Is there any alternative workaround to the above solution in the meantime?
I tried weird workarounds like this one
// @ts-expect-error: :s async function getUnifiedPluginHack() { const {unified} = await import('unified'); type Attachers = ReturnType<typeof unified>['attachers']; type Attacher = Attachers[number]; type PluginP = Attacher[0]; return null as any as PluginP; } type Plugin = Awaited<ReturnType<typeof getUnifiedPluginHack>>;
And of course it didn't work 😅 TS error + the type is generic
src/index.ts:15:16 - error TS2841: The type of this expression cannot be named without a 'resolution-mode' assertion, which is an unstable feature. Use nightly TypeScript to silence this error. Try updating with 'npm install -D typescript@next'.
15 async function getUnifiedPluginHack() {
Reacted by tonywu6Isn't TS 5.3 beta fixing this issue Andrew Branch (@andrewbranch) ?

Yep!
Reacted by Sébastien Lorber and James NestaReacted by Sébastien Lorber, Niket Pathak and Mykola Symotiuk- added 7 commits that reference this issue
on Oct 5, 2023 - added a commit that references this issue
on Jul 21, 2026
Suggestion
🔍 Search Terms
es esm module cjs commonjs type import moduleResolution node16 nodenext
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
Allow CommonJS modules to import types from ES Modules without an
async import()ifimport typesis specified.With
moduleResolution: "node16"enabled, we now get this very helpful error message when importing an ES Module from a CommonJS module (thank you!):However, it is often the case that module will export a types API as well as a runtime API. Sometimes, we only want to import the types from a package. Typescript has the very helpful
import typedirective to acommodate this use case. However, if we want to import the types from an ES Module, we still get the following error:Because
import types are stripped from runtime code, there is no need to throw this error.📃 Motivating Example
Because this error is thrown, it forces us to add an unnecessary async import somewhere in our file, causing non-ergonomic development at best, and unnecessary runtime complexity at worst.
Consider:
It also (very unfortunately) makes it simply impossible to create and re-export derivative types from a module like this:
💻 Use Cases
See above motivating example. I'm currently using
// @ts-expect-errorto get past this, but would be great not to! This error should obviously still throw ifimportsNotUsedAsValuesis set topreserve.