工程化
TypeScript 配置
严格模式策略、verbatimModuleSyntax、全局类型增强、共享 tsconfig 体系
总体策略
| 维度 | 策略 |
|---|---|
| 严格度 | 全仓库 strict: true + noUncheckedIndexedAccess: true |
| 模块 | ESM-first,module: ESNext、moduleResolution: bundler |
| 编译目标 | ESNext(不降级,交给 Vite / esbuild) |
| 类型分发 | verbatimModuleSyntax: true,强制 import type |
| 共享 | @skyroc/tsconfig 7 个预设,全部包通过 extends 引用 |
| TS 版本 | ^6.0.3(通过 catalog:core 集中管理) |
| 类型检查 | pnpm typecheck → turbo run typecheck → 各包 tsc --noEmit |
7 个共享预设
| 预设 | 适用 |
|---|---|
base.json | 所有 TS 包基线 |
library.json | 发布到 npm 的库(emit dts) |
node.json | Node 工具 / 脚本 |
web.json | Web 端含 DOM lib |
web-app.json | Web 应用(admin) |
react-native.json | RN 库 |
react-native-app.json | RN 应用 |
详见 @skyroc/tsconfig。
必须了解的严格选项
strict
启用所有严格模式:strictNullChecks、noImplicitAny、strictFunctionTypes、strictPropertyInitialization 等。
noUncheckedIndexedAccess
数组 / 对象索引访问自动加 | undefined,杜绝 arr[0] 默认非空的假设。
const arr = [1, 2, 3];
const first = arr[0]; // number | undefined写代码时必须显式判空或用 arr.at(0)、arr[0]!。
verbatimModuleSyntax
类型 import 必须显式写 type:
import type { User } from './types';
import { fn, type Foo } from './module';好处:
- 编译产物无运行时副作用;
- bundler 精准 tree-shake;
type Foo不会被打包;
绝大多数 ESLint / Oxlint 配置会同步开启 typescript/consistent-type-imports 强化这一点。
全局类型增强
在 web-app.json 中通过 types 字段引入:
"types": [
"vite/client",
"unplugin-icons",
"@skyroc/types",
"@skyroc/web-admin-theme"
]效果:
| 命名空间 | 含义 | 来自 |
|---|---|---|
Api.* | 后端 API 请求 / 响应类型 | @skyroc/types + 应用 typings |
Router.* | 业务路由 meta / element key | @skyroc/types |
App.* | 应用级类型(service options 等) | @skyroc/types |
Theme.* | 主题 token / palette / 配置 | @skyroc/web-admin-theme |
ImportMetaEnv | import.meta.env.VITE_* | vite/client + 应用增强 |
~icons/* | import IconHome from '~icons/lucide/home' | unplugin-icons |
业务代码可以直接:
const user: Api.Auth.UserInfo = ...;
const t: Router.RouteKey = '/dashboard/analysis';不需要 import 类型。
应用层 typings 目录
apps/admin/src/typings/
├── api.d.ts # 业务 API 类型(Api.Sys.UserListItem 等)
├── app.d.ts # 应用级类型
├── router.d.ts # 路由 element key 等
├── elegant-router.d.ts
└── env.d.ts # import.meta.env 增强这些文件不需要 import,TS 通过 tsconfig.json 的 include 自动加载。
noEmit vs 输出 dts
| 包类型 | 配置 | 说明 |
|---|---|---|
| 应用 | 仅 typecheck,不 emit | Vite 单独编译 |
| 库(tsdown 构建) | tsdown 内部生成 dts | 不靠 tsc |
| 库(极少数 tsc) | emitDeclarationOnly: true | extends library.json |
| Internal 配置包 | 仅 emit dts | @skyroc/config/vitest |
tsdown 默认产 *.d.mts + *.d.ts,由 构建体系 详细说明。
paths 与 alias
| 应用 | paths |
|---|---|
apps/admin | @/* → src/*、~/* → 项目根 |
| 包内部 | 一律相对 import;避免设置包内 paths |
理由:包内 paths 会破坏 tsdown 编译时的路径解析。
ESM-only 与 CJS 兼容
| 维度 | 配置 |
|---|---|
包 type | 全部 "module" |
| 入口 | 默认 index.mjs |
exports.import / exports.types | tsdown 自动写入 |
exports.require | 不输出(除非有强需求) |
下游用 ESM 即可,CJS 用户需另行兼容。
类型联调流程
- 写代码 → 编辑器实时报错(VS Code TS Server);
- 提交前
pnpm typecheck; - CI 跑
turbo run typecheck; - PR 中失败的 typecheck 视为 blocker。
升级 TS 版本
由 pnpm-workspace.yaml 集中管理:
overrides:
typescript: ^6.0.3
catalogs:
core:
typescript: ^6.0.3升级流程:
- 改
pnpm-workspace.yaml两处; pnpm install;pnpm typecheck全仓库验证;- 修复破坏性变更(一般是 strict 收紧 / lib types 变动);
- 提交。
常见 Bug 与避坑
| 现象 | 原因 / 对策 |
|---|---|
Cannot find namespace 'Api' | 应用 tsconfig.json 未 extends web-app.json |
Type instantiation is excessively deep | 通常是 @skyroc/type-utils 的 path 类型嵌套太深,限制泛型层级 |
包内 import 形如 @skyroc/utils 报错 | 包未把 @skyroc/utils 写进 dependencies(不是 devDependencies) |
| dts 缺少类型 | tsdown 配置漏写 entry 子入口 |
verbatimModuleSyntax 报错 | 漏写 import type,按提示修 |