三块面板:TS 源码 / 写死的 tsc 报错样本(非现场运行)/ 可点跑的等价 JS。看联合的「取共有成员」、可辨识联合的 switch 收窄。
type ID = string | number
function render(id: ID) {
id.toString() // ✓ string/number 都有
id.length // ✗ number 上没有 length
id.toUpperCase() // ✗ 未收窄前不能用某一分支独有的成员
}
length/toUpperCase 只在 string 上有,编译器不能保证 id 就是 string,所以拦下。擦除后 switch(s.kind) 照常按标签分派——TS 的收窄读的就是这个标签字段。点不同形状看面积。
type Shape =
| { kind: 'circle'; r: number }
| { kind: 'rect'; w: number; h: number }
| { kind: 'triangle'; base: number; height: number }
function area(s: Shape): number {
switch (s.kind) {
case 'circle': return Math.PI * s.r ** 2 // s 收窄成 circle,s.r 合法
case 'rect': return s.w * s.h // 只能访问 w/h
case 'triangle': return (s.base * s.height) / 2
default:
const _never: never = s // 处理全后 s 应为 never;漏支就在这里报错
return _never
}
}
type HasName = { name: string }
type HasAge = { age: number }
type Person = HasName & HasAge // { name: string; age: number }
const p: Person = { name: '阿蓝', age: 18 } // 两边字段都要给