You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何TypeScript允许在CommonJS模块中使用import语法?

TypeScript模块系统疑问:CommonJS环境下为何允许import语法?

环境配置

  • Child.ts:
export const child = "Child";
  • Parent.ts:
import { child } from "./Child";
console.log(child);
  • tsconfig.json:
{
  "compilerOptions": {
    "module": "node16",
    "esModuleInterop": true // 设为true或false无影响
  }
}
  • package.json未设置"type":"module"

问题

根据TypeScript的模块格式检测文档,原本预期:由于package.json未设置"type":"module",TypeScript会将Parent.ts和Child.ts视为CommonJS模块,应该对import语法报错并建议使用require(),但实际TypeScript允许在这类文件中使用import语法。想知道忽略了什么,是否是tsconfig的配置导致?

补充

另外,ESM模块要求相对路径带扩展名,照此TypeScript应该对import { child } from "./Child";报错,要求写成import { child } from "./Child.ts";,但实际也未报错。


解答

你混淆了TypeScript源文件的语法支持和最终编译输出的模块格式两个核心概念:

  1. 源文件语法的兼容性:TypeScript本身允许你在源文件中使用ESM的import/export语法,无论最终编译目标是CommonJS还是ESM。当module设为node16且package.json无"type":"module"时,TypeScript会自动将你的ESM语法编译成CommonJS格式的代码(比如把import转换为require,export转换为module.exports相关逻辑),而非在编译阶段就报错禁止使用ESM语法。

  2. 扩展名的处理逻辑:Node.js的ESM要求导入带扩展名是针对编译后的.js文件的,但TypeScript在源文件解析阶段有自己的模块查找规则——它会自动尝试补充.ts、.d.ts、.tsx等扩展名来定位文件。当编译完成后,TypeScript会自动将导入路径替换为符合Node.js要求的格式(比如把./Child替换为./Child.js,对应编译后的CommonJS文件),因此源文件中不需要写.ts扩展名也不会报错。

简单来说,TypeScript作为转译层,会帮你处理源语法到目标模块格式的转换,以及扩展名的适配,这就是你看到和预期不符的核心原因。

内容的提问来源于stack exchange,提问作者H-H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:17:41