为何TypeScript不允许从ES模块向CommonJS模块导入类型?
问题分析与解决办法
为什么会出现这个错误?
这不是TypeScript的Bug,而是它有意设计的行为。虽然import type语句最终会被完全移除,不会生成require调用,但TypeScript在编译阶段会严格校验模块之间的兼容性——Node.js本身禁止CommonJS模块同步导入ESM模块,TypeScript的这个错误正是对齐了Node.js的模块系统限制,它不会因为导入的是类型就跳过模块格式的校验。
解决办法
这里有几个实用的解决方案:
1. 将共享类型移至.d.ts声明文件
.d.ts文件不属于CommonJS或ESM模块范畴,是中性的类型声明载体,CJS和ESM模块都能自由导入其中的类型。
- 把
types.ts重命名为types.d.ts,内容保持不变:
// types.d.ts export interface Options {}
- 在
processOptions.cts中导入:
// processOptions.cts import type { Options } from "./types.d.ts";
2. 使用类型查询绕开静态导入校验
通过typeof import()的方式获取类型,这种方式不会触发静态导入的模块兼容性检查,也不会生成任何运行时代码:
// processOptions.cts type Options = (typeof import("./types.ts"))["Options"];
3. 统一模块格式(按需选择)
如果你的项目允许,可以调整文件的模块格式:
- 若希望
types.ts兼容CJS,可将其重命名为types.cts,但这样ESM模块导入时需要指定.cts扩展名; - 若不需要
processOptions.cts是CJS,可将其重命名为processOptions.ts,使其成为ESM模块,就能直接导入types.ts。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

