TypeScript 与自动导入
本教程共 45 篇 · 第 29 篇 · 更新于 2026-08-13 · 约 3 分钟阅读
本节目标:搞懂 WXT 的类型从哪来、路径别名怎么配,再学会自动导入机制的使用、关闭与显式导入。
WXT 是 TypeScript 友好型框架:类型自动生成、别名开箱即用、API 免 import。这一章把它们逐个讲清楚。
wxt prepare:类型从哪来
WXT 会在构建前生成一堆类型文件。执行 wxt prepare 后,项目里会出现 .wxt/tsconfig.json——这是 WXT 生成的基座配置。你根目录的 tsconfig.json 只需要继承它:
// <rootDir>/tsconfig.json
{
"extends": ".wxt/tsconfig.json"
}
如果是 monorepo,可能不想继承这份配置。那就把生成的声明文件手动引入 TypeScript 项目:
/// <reference path="./.wxt/wxt.d.ts" />
Note
wxt prepare也是 §06 提到的入口加载机制的一部分,dev/build 命令会自动执行它。手动跑一遍的场景主要是:装完依赖后让编辑器恢复类型提示。
路径别名:不用写一长串相对路径
WXT 默认提供四个别名(§22 已讲过它们在模块导入中的作用,这里看配置层面):
| 别名 | 指向 | 示例 |
|---|---|---|
~~ | <rootDir>/* | import "~~/package.json" |
@@ | <rootDir>/* | import "@@/package.json" |
~ | <srcDir>/* | import "~/utils/strings" |
@ | <srcDir>/* | import "@/utils/strings" |
想加自己的别名,别改 tsconfig.json,要用 wxt.config.ts 的 alias 选项:
import { resolve } from 'node:path';
export default defineConfig({
alias: {
testing: resolve('utils/testing'), // 目录别名
strings: resolve('utils/strings.ts'), // 文件别名
},
});
这样配的好处:下次跑 wxt prepare,别名会同时写进 .wxt/tsconfig.json(让编辑器认识)和打包器(让构建能解析)。两处同步,不会出现「编辑器不报错、构建却找不到」的怪问题。
import { fakeTab } from 'testing/fake-objects';
import { toLowerCase } from 'strings';
自定义编译选项的两条路
想改编译选项,有两条路:
- 直接覆盖:在根目录
tsconfig.json里重写compilerOptions,比如"jsx": "preserve"。适合布尔值、单个枚举这类简单设置。 - 钩子合并:用
prepare:tsconfig钩子改生成前的配置对象,适合paths、lib这种需要「追加」的复杂选项:
export default defineConfig({
hooks: {
'prepare:tsconfig': (wxt, { tsconfig }) => {
tsconfig.compilerOptions.lib.push('WebWorker');
},
},
});
为什么需要钩子?因为 tsconfig 的继承机制做不到「给数组追加一项」——子配置写 lib 就直接覆盖了父配置。钩子可以在文件写出前直接改对象,加、删、合并都行。
自动导入:不用 import 就能用
WXT 用 unimport(和 Nuxt 同款工具)实现自动导入(auto-imports)。默认情况下,两样东西会被自动导入:
- WXT 自己的全部 API,比如
defineContentScript、defineBackground - 项目里四个目录的导出:
<srcDir>/components/*、<srcDir>/composables/*、<srcDir>/hooks/*、<srcDir>/utils/*
这些目录里文件的所有具名导出和默认导出,在项目任何地方都能直接用,不用写 import。想看完整清单,跑一次 wxt prepare,然后打开 .wxt/types/imports-module.d.ts。
自动导入的配置项通过 imports 字段传给 unimport:
export default defineConfig({
imports: {
// unimport 的配置项
},
});
编辑器与 ESLint
TypeScript 和编辑器要识别自动导入的变量,前提是跑过 wxt prepare。建议把它挂到 postinstall 脚本,装完依赖自动执行:
// package.json
{
"scripts": {
"postinstall": "wxt prepare"
}
}
ESLint 默认不知道这些「凭空出现」的变量。WXT 检测到项目装了 ESLint 时,会自动生成对应的 globals 配置;没自动生成就手动开启:
export default defineConfig({
imports: {
eslintrc: {
enabled: 9, // ESLint >= 9;ESLint <= 8 用 8
},
},
});
然后在 ESLint 配置里引入生成的文件:
// eslint.config.mjs(ESLint >= 9)
import autoImports from './.wxt/eslint-auto-imports.mjs';
export default [autoImports];
ESLint 8 及以下则是在 .eslintrc.mjs 里 extends: ['./.wxt/eslintrc-auto-import.json']。
不喜欢自动导入?两条退路
自动导入不是强制绑定的。
方式一:整体关闭。
export default defineConfig({
imports: false,
});
方式二:用 #imports 显式导入。 所有 WXT 的 API 都可以从这个虚拟模块手动引入:
import {
createShadowRootUi,
ContentScriptContext,
MatchPattern,
} from '#imports';
即使没关自动导入,#imports 也能用。它本质上就是自动导入的「显式形态」:同一个来源,一次是隐式全局,一次是显式 import。mkext 这类团队项目为了代码可读性,常用 imports: false 配合 #imports,各入口文件开头一眼就能看出用了哪些 API。
小结
- 项目继承
.wxt/tsconfig.json,@/、@@/等别名开箱即用。 - 自动导入免去手写 import,
#imports是它的显式形态,可按团队习惯二选一。 - ESLint 与类型生成都挂在
wxt prepare上,装完依赖记得跑。