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

TypeScript编写的库无法在JavaScript和TypeScript项目中同方式导入

公共库同时兼容TS/JS项目同导入语法解决方案

问题本质

问题根源是Node.js对CommonJS和ES模块的互操作规则限制:当ES模块("type": "module"的JS项目)导入CommonJS模块时,不会自动将CommonJS的exports.default提升为默认导入值,所以导入拿到的是完整的exports对象,需要手动取.default才能拿到目标类。

推荐方案:双产物输出(CJS+ESM)

这是目前Node/前端公共库的标准兼容方案,同时输出两套编译产物,让不同模块系统的项目自动匹配对应产物,无需修改用户侧的导入写法。

第一步:调整TypeScript配置

新增两份编译配置,分别对应CommonJS和ESM产物输出:

  1. 基础配置tsconfig.json(共用规则):
{
    "compilerOptions": {
        "target": "es2017",
        "declaration": true,
        "esModuleInterop": true,
        "skipLibCheck": true
    },
    "include": ["src"],
    "exclude": ["node_modules", "**/__tests__/*"]
}
  1. CommonJS配置tsconfig.cjs.json:
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "module": "commonjs",
        "outDir": "./lib/cjs"
    }
}
  1. ESM配置tsconfig.esm.json:
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "module": "ESNext",
        "moduleResolution": "NodeNext",
        "outDir": "./lib/esm",
        "declarationDir": "./lib/types"
    }
}

第二步:修改package.json配置

增加模块入口匹配规则,让Node/打包工具自动识别对应产物:

{
    "main": "./lib/cjs/classA.js",
    "module": "./lib/esm/classA.js",
    "types": "./lib/types/classA.d.ts",
    "files": ["lib/**/*"],
    "scripts": {
      "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json"
    },
    "exports": {
      ".": {
        "import": "./lib/esm/classA.js",
        "require": "./lib/cjs/classA.js",
        "types": "./lib/types/classA.d.ts"
      }
    }
}

第三步:添加模块类型标记

在lib/esm目录下新增package.json,标记该目录下的JS文件为ES模块:

{"type": "module"}

业务代码无需修改

原有的classA.ts的export default写法不需要调整,编译后两套产物会自动适配各自的模块系统:

  • ESM产物保留标准export default语法,ES模块项目导入时直接拿到默认导出
  • CJS产物用exports.default导出,TS项目开启allowSyntheticDefaultImports后会自动适配

轻量兼容方案(仅单CJS产物)

如果不想维护双产物,可以直接在导出逻辑上加兼容代码,无需修改配置:
修改classA.ts的导出部分:

import { IClassA } from './classAInterfaces';

export default class ClassA<T> implements IClassA<T> {
  constructor() {
  }
  size() {
    return 0
  }
}

// 兼容ESM导入CommonJS的场景
if (typeof module !== 'undefined' && module.exports) {
  module.exports = ClassA;
  module.exports.default = ClassA;
}

这种方式编译后的CJS产物同时兼容:

  • TS项目默认导入:allowSyntheticDefaultImports会自动匹配default导出
  • ESM项目默认导入:Node拿到的module.exports直接就是ClassA,不需要取.default

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:15:03