Skip to main content
Extension.js 用 SWC 编译 TypeScript,它只擦除类型,从不检查类型。类型检查是你用 tsc 单独运行的一步。本页说明这一步需要哪些包,才能解析 chrome.*browser.*

Extension.js 会生成什么

当项目使用 TypeScript 时,extension devextension build 会在 package.json 旁边写下一个 extension-env.d.ts 文件。它在每次运行时都会被重新生成,所以不要编辑它。 这个文件会引入 extension 包发布的环境类型:
extension-env.d.ts
这些引用会给你: EXTENSION_* 环境变量键也在这里被赋予类型。这就是 process.env.EXTENSION_MODE 不需要额外配置就能解析的原因。

为 chrome 命名空间安装 @types/chrome

extension/types 自己声明了 browser 全局变量,但它是通过一条引用去够到 chrome 命名空间的:
只有当你的项目里装了 @types/chrome,这条引用才解析得到。Extension.js 不会安装它,模板也不会声明它。 因此,一个调用了 chrome.storage 的脚手架 TypeScript 项目跑 tsc 会失败:
安装这个包就能清掉它:
再跑一次检查,错误就没了:
别的什么都没变。在安装之前构建就已经成功了,因为 SWC 从来不读类型。

当你改用 browser.* 时

browser 全局变量由 extension/types 赋予类型,它把这个变量映射到 webextension-polyfill 上。想要完整的命名空间形状,请再装上配套的类型包:
同一个选择在运行时那一侧的样子,请阅读 跨浏览器兼容性

让 extension-env.d.ts 留在 include 列表里

只有当 TypeScript 读到它时,这个生成的文件才有用。脚手架生成的 tsconfig.json 会点名它:
tsconfig.json
当 Extension.js 为一个还没有 tsconfig.json 的项目写下这份文件时,那份文件里不带 include 数组。TypeScript 于是会读取项目目录下的每一个文件,所以照样能找到 extension-env.d.ts。而一个你自己写的、漏掉了这个文件的 include 数组,会让资源导入和 browser 全局变量一起失效。

症状与修复

最佳实践

  • extension-env.d.ts 当作构建产物看待。愿意的话可以提交它,但绝不要编辑它。
  • 任何调用 chrome.* 的 TypeScript 项目都该加上 @types/chrome,包括你从模板生成的那些。
  • 在持续集成中跑 tsc --noEmit。Extension.js 的构建不会因为类型错误而失败。

下一步