如何在 TypeScript 中导入 JSON 而不抓狂
\n\n如果你曾经尝试在 TypeScript 中执行 import data from './config.json',你就会知道那种感觉:编译器变红,报错,并抛出 Cannot find module 错误。熟悉的痛苦?没错!关于在 TypeScript 中导入 JSON 的问题是 Stack Overflow 上最热门的问题之一。这并不奇怪:JSON 无处不在——配置文件、本地化、模拟数据、静态列表。但 TypeScript 默认无法处理 JSON 文件。
在本教程中,我们将探讨在 TypeScript 中导入 JSON 的所有方法——从简单地在 tsconfig 中启用一个标志,到高级的类型化。你将学会如何让 TypeScript 与 JSON 友好相处,并且再也不会看到那个红色错误。我们开始吧!
\n\n为什么 TypeScript 看不到 JSON?
\n在深入代码之前,让我们先了解原因。TypeScript 是 JavaScript 的超集,它添加了静态类型化。默认情况下,TypeScript 编译器期望所有导入的模块都是 .ts 或 .js 文件。JSON 不是模块,它是一种数据格式。TypeScript 根本不知道如何解释它。
\n解决方案有两个方面:
\n- \n
- 配置编译器 — 通过
resolveJsonModule标志启用 JSON 支持。 \n - 模块声明 — 如果该标志不合适,手动为 JSON 文件描述类型。 \n
方法 1:启用 resolveJsonModule(正确的方式)
\n最简单且推荐的方法是在 tsconfig.json 中添加 resolveJsonModule 选项。这个标志告诉 TypeScript:“嘿,朋友,让我们像导入普通模块一样导入 JSON”。
// tsconfig.json\n{\n "compilerOptions": {\n "resolveJsonModule": true,\n "esModuleInterop": true\n }\n}\n之后,你可以放心地编写:
\n// config.ts\nimport config from './config.json';\n\nconsole.log(config.apiUrl); // 有效!\nconsole.log(config.port); // 有效!\n这里发生了什么?TypeScript 会自动为导入的 JSON 创建类型。如果你的 JSON 中有字段 apiUrl: string 和 port: number,TypeScript 会推断出它们的类型并检查使用情况。很酷,对吧?
但有一个细节:resolveJsonModule 还需要启用 esModuleInterop 或 allowSyntheticDefaultImports,以便默认导入正常工作。否则,你在尝试导入时会遇到错误。
方法 2:使用命名导出导入
\n有时你不需要整个 JSON,只需要某些特定字段。TypeScript 也支持这一点:
\nimport { apiUrl, port } from './config.json';\n\nconsole.log(apiUrl); // 字符串\nconsole.log(port); // 数字\n这得益于打包工具(Webpack、Vite)中的所谓“tree-shaking”,但在 TypeScript 层面,这仅仅是对象的解构。但请记住:如果你使用 resolveJsonModule,TypeScript 会自动为所有字段创建类型,因此你可以放心地导入整个对象或其部分。
方法 3:使用 require 代替 import(适用于旧项目)
\n如果你在一个由于某些原因无法启用 resolveJsonModule 的项目中工作(例如,与其他设置冲突),你可以使用老牌的 require:
const config = require('./config.json');\n\nconsole.log(config.apiUrl); // 有效,但没有类型\n这种方法的缺点很明显:你失去了类型化。TypeScript 不知道 config 里面有什么,会将其类型视为 any。这为错误敞开了大门。如果一定要使用 require,至少添加一个类型声明:
interface Config {\n apiUrl: string;\n port: number;