写好 TypeScript 的 6 个实用习惯
不聊类型体操,只聊日常开发里真正能减少 bug、提升可读性的 TypeScript 习惯。
发布于
2 分钟阅读
目录
TypeScript 上手容易,写「好」却需要刻意练习。这里的「好」不是炫技,而是:让编译器替你多想一步,让半年后的自己读得懂。以下 6 个习惯,都是我在真实项目里反复验证过的。
1. 让 unknown 成为 any 的替代品
any 会把类型检查在传播路径上全部关掉。实在拿不准类型时,用 unknown 强迫自己先收窄:
function parse(raw: string): unknown {
return JSON.parse(raw);
}
const data = parse(input);
if (typeof data === 'object' && data !== null && 'id' in data) {
// 这里 TS 已经知道 data 是 object
}
2. 用判别联合建模「状态」
有状态机味道的需求,优先用判别联合而不是一堆布尔位:
type FetchState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; message: string };
好处是非法状态无法表达——你不可能写出「成功但没有数据」的对象。
3. satisfies 比 as 诚实
as 是「信我」,satisfies 是「帮我验证」:
const routes = {
home: '/',
blog: '/blog/',
about: '/about/',
} satisfies Record<string, `/${string}/`>;
写错路径格式会立刻报错,而且 routes 保留了字面量类型的推导。
4. 从源头收窄,而不是到处断言
拿到外部数据(接口响应、URL 参数、localStorage)时,在边界处做一次完整校验,内部就放心用:
const stored = localStorage.getItem('theme');
const theme = stored === 'dark' ? 'dark' : 'light';
一行收窄,后面全是干净类型。
5. 善用模板字面量类型
URL、事件名、CSS 变量这类字符串,可以用模板字面量类型描述结构:
type CategoryPath = `/categories/${string}/`;
function goto(path: CategoryPath) {
window.location.assign(path);
}
goto('/blog/'); // ❌ 类型错误
6. 检查开关全部打开
最后也是最重要的:配好 tsconfig,让工具替你把关。
| 配置 | 作用 |
|---|---|
strict: true |
一揽子严格检查,必开 |
noUncheckedIndexedAccess |
索引访问结果视为 T | undefined |
noEmit |
只做类型检查,交给打包器产物 |
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"noUncheckedIndexedAccess": true
}
}
小结
类型系统的价值不在于注解数量,而在于把运行时才暴露的问题搬到编译期。上面 6 个习惯没有一个是新知识,但每一里都少踩一个坑。