«React refers to a UMD global»:TypeScript 如何发疯

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:当编译器说「不」

\n

你打开心爱的编辑器,写了几行 TypeScript 代码,运行构建——然后突然看到这个:'React' refers to a UMD global, but the current file is a module。如果你曾经遇到过这个错误,你就会知道它有多么令人沮丧。看起来一切正常:有导入,React 已安装,但编译器却固执地拒绝理解你的意图。

\n\n

这个错误不仅仅是一个偶然的 bug。它揭示了 TypeScript、构建系统和模块格式的深层工作机制。在本文中,我们不仅会展示如何修复它。我们将深入「引擎盖下」,弄清楚为什么会出现React refers to a UMD global 错误,TypeScript 如何区分 UMD 和 ESM,以及如何正确配置你的项目,以便永远忘记它。

\n\n

本文面向已经熟悉 React 和 TypeScript,但想了解内部机制的开发者。准备好了吗?开始吧!

\n\n

什么是 UMD,为什么 TypeScript 知道它?

\n\n

在分析错误之前,让我们回顾一下 JavaScript 中的模块格式。当你编写 import React from 'react' 时,TypeScript 必须理解这段代码来自哪里以及如何使用它。有几种标准:

\n\n
    \n
  • ESM (ECMAScript Modules) — 使用 import/export 的现代标准。
  • \n
  • CommonJS — Node.js 的格式,使用 require/module.exports。
  • \n
  • UMD (Universal Module Definition) — 一种混合格式,既可以在浏览器中工作(通过全局变量),也可以在 Node.js 中工作(通过模块)。
  • \n
\n\n

React 以多种格式分发,包括 UMD。当你通过 npm 安装 React 时,你会得到 ESM 版本(例如,带有 export default 的 index.js)。但旧版本或某些构建可能使用 UMD,其中 React 作为全局变量 window.React 可用。

\n\n

TypeScript 分析类型声明文件(.d.ts)。对于 React,这是 @types/react 包。在其中,有一个声明指出:「React 可作为 UMD 全局变量使用」。当 TypeScript 看到你的文件被标记为模块(例如,包含 import 或 export)时,它开始感到困惑:「你正在导入 React,但声明说它是一个全局变量。而文件是一个模块。该怎么办?」

\n\n

为什么会出现错误:「React refers to a UMD global, but the current file is a module」?

\n\n

当 TypeScript 无法明确确定如何处理 React 的导入时,就会出现此错误。这是一个典型场景:

\n\n
// App.tsx\nimport React from 'react';\nimport { useState } from 'react';\n\nconst App: React.FC = () => {\n    const [count, setCount] = useState(0);\n    return <div>{count}</div>;\n};\n\nexport default App;\n
\n\n

你运行编译,TypeScript 抛出错误:'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.

\n\n

为什么?因为在 @types/react 中有这样一个声明(简化版):

\n\n
// 在 @types/react 的 index.d.ts 文件中\nexport = React;\nexport as namespace React;\n\ndeclare namespace React {\n    // ...类型\n}\n
\n\n

关键行是 export as namespace React。它告诉 TypeScript:「这个模块也可以作为全局变量 React (UMD) 使用」。当你的文件是一个模块(包含 export)时,TypeScript 可能无法理解你是想使用全局的 React 还是导入的 React。结果就是冲突。

\n\n

如何修复:三种经过验证的方法

\n\n

方法 1:显式导入(最常见)

\n\n

最简单的方法是确保你显式导入 React,即使

博客

书籍推荐