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

TypeScript导入JSON时模块包裹行为不一致的问题如何解决?

行为不一致的原因

这个问题的本质是TypeScript类型推断和实际运行时的模块结构不匹配,由两个规则共同导致:

  1. 你用的构建工具(比如Webpack、旧版Vite)处理JSON文件时,默认会生成两种导出:JSON每个顶级字段的单独命名导出、完整JSON对象的default导出。你用import * as a语法得到的是完整的模块命名空间对象,不是JSON本身,所以访问a.one刚好能命中命名导出的字段拿到值,但模块对象本身还带了default、__esModule等内置属性,直接赋值的话自然就会拿到完整的Module实例。
  2. 当你开启了TS的resolveJsonModule配置后,TS会把import * as导入的JSON模块的类型直接推断为JSON本身的结构,既允许你直接访问字段,也允许你把导入值直接当做JSON对象赋值,不会提示你这是模块命名空间对象,就造成了“内部访问属性正常、直接赋值异常”的不一致现象。

无需工具函数的解决方案

方案1:改用默认导入(最推荐)

直接把导入语句改成默认导入,拿到的直接是完整的JSON对象,所有用法都符合预期:

// 修改导入语句
import a from "./a.json";
import b from "./b.json";

// 后续代码不需要调整
Things.one = a.one;
Things.two = a.two;
Things.three = b;

只需要在tsconfig.json中开启allowSyntheticDefaultImports配置即可,如果已经开启了esModuleInterop,这个配置会自动生效。

方案2:赋值时显式取default

如果不想修改TS配置,只需要在赋值完整JSON对象的时候主动取模块的default属性即可:

Things.three = b.default;

方案3:关闭构建工具的JSON命名导出

如果用的是Webpack,可以修改json-loader的配置关闭namedExports,强制JSON只能通过default导出,从根源上避免两种用法的行为差异:

// webpack.config.js 对应规则配置
module: {
  rules: [
    {
      test: /\.json$/,
      loader: 'json-loader',
      options: { namedExports: false }
    }
  ]
}

方案4:开启esModuleInterop

直接在tsconfig.json中设置esModuleInterop: true,TS会自动处理JSON、CommonJS模块的导入兼容,默认导入的类型和运行时行为会完全对齐,不需要额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 19:57:03