lang
lang/typescript/types/declaration-and-paths.md
low
typescript-declaration-and-paths
为无类型 JS 库补 .d.ts 声明文件并配 tsconfig paths 别名替代深相对路径。Use when 引入无类型第三方库报红 / 声明全局类型或挂载 window / 配置 @/ 别名 / import 出现 ../../..
declaration file.d.tsdeclare moduledeclare globaltsconfig pathspath alias声明文件路径别名
paths
frontend/src/**/*.tsfrontend/src/**/*.tsx
TypeScript · 声明文件与路径别名
规则
决策点一:无类型库补 .d.ts,绝不 as any 抹掉报红。 声明文件只描述类型、不产 JS 代码。
| 场景 | 写法 | 放哪 |
|---|---|---|
第三方 JS 库无 @types |
declare module 'foo' { ... } |
src/types/foo.d.ts |
全局类型 / 挂 window |
declare global { interface Window { ... } } |
src/types/global.d.ts |
资源导入(*.svg/*.css) |
declare module '*.svg' |
src/types/assets.d.ts |
declare global必须写在一个 module(文件里有import/export)内,否则视作普通脚本污染全局。
决策点二:路径别名只配 @/ 一个根指向 src/,别滥设多别名。 多别名(@components @utils …)增加心智与配置维护成本,统一 @/components 即可。
// tsconfig.json —— 编译期类型解析
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } }
坑:
tsconfig paths只管类型检查,运行时/打包需同步配——否则编译过但跑起来「找不到模块」。
- Vite:
resolve.alias配@→src(或装vite-tsconfig-paths自动读)。- Jest:
moduleNameMapper配^@/(.*)$→<rootDir>/src/$1(或ts-jest的pathsToModuleNameMapper)。
反例 · 正例
// ❌ 反例:无类型库直接 any,丢掉一切类型与补全
import legacyChart from "legacy-chart"; // 报红 → 被迫 (legacyChart as any).render()
// ❌ 反例:深相对路径,目录一移全断
import { formatMoney } from "../../../../shared/utils/money";
// src/types/legacy-chart.d.ts —— 声明文件不产代码,只描述类型
declare module "legacy-chart" {
// 声明库导出的形状,按需补关键方法即可
export interface ChartOptions {
data: number[];
color?: string;
}
export function render(el: HTMLElement, options: ChartOptions): void;
}
// src/types/global.d.ts —— 全局类型挂载 window
// 文件需含 import/export 才构成 module,declare global 才生效
export {};
declare global {
interface Window {
__APP_VERSION__: string;
}
}
// ✅ 业务文件:别名替代深相对,目录迁移不受影响
// 取格式化工具:统一从 @/ 根引入
import { formatMoney } from "@/shared/utils/money";
// 取声明过的库:类型与补全齐全
import { render } from "legacy-chart";
// 渲染图表:无前置校验,直接编排
const draw = (el: HTMLElement, data: number[]): void => render(el, { data });
自检
- [ ] 无类型库是补了
.d.ts(declare module)而非as any抹红? - [ ] 全局类型放
global.d.ts,且文件含export {}让declare global生效? - [ ] 路径别名只配
@/→src/*一个根,没滥设多别名? - [ ]
tsconfig paths配了后,Viteresolve.alias/ JestmoduleNameMapper也同步配了? - [ ] import 里没再出现
../../../..这类深相对路径?
相关
- 父:
./index.md - 跨引:
../module/index.mdESM 模块规范与 barrel export