TypeScript中如何对类静态实例实现编译期穷尽匹配?
实现TypeScript编译期穷尽匹配检查的方案
问题根源:直接引用静态值作为类型导致报错
你之前尝试定义type ShapeType = Shape.Circle | Shape.Rectangle | Shape.Triangle时出现语法错误,是因为**Shape.Circle是运行时的值,不是类型**——TypeScript的类型上下文里只能引用类型,要获取静态实例的类型,必须用typeof操作符。
解决步骤
1. 定义静态实例的联合类型
通过typeof Shape[keyof typeof Shape]可以自动获取Shape类所有静态实例的联合类型,不用手动枚举每个静态属性,后续新增实例时也能自动更新类型:
class Shape { constructor( public readonly angles: number, public readonly color: string ){} static Triangle = new Shape(3, "red"); static Rectangle = new Shape(4, "blue"); static Circle = new Shape(0, "green"); } // 自动生成所有静态Shape实例的联合类型 type ShapeInstance = typeof Shape[keyof typeof Shape];
2. 用never类型实现穷尽检查
定义一个断言函数,配合switch的default分支,只要有未覆盖的实例分支,TypeScript就会在编译期报错:
// 断言函数:仅接收never类型参数,用于触发编译错误 function assertNever(value: never): never { throw new Error(`Unexpected shape: ${value}`); } function shapeCatchPhrase(shape: ShapeInstance): string { switch (shape) { case Shape.Triangle: return "Three is a magic number"; case Shape.Rectangle: return `Are you a ${shape.color} square?`; case Shape.Circle: return `Oh! Look at your ${shape.angles} angles!`; // 如果新增了Shape静态实例但未添加对应case,这里会触发编译错误 default: return assertNever(shape); } }
3. 进阶:限制外部创建实例(可选)
如果要完全模拟枚举的特性,防止外部通过new Shape()创建非法实例,可以把构造函数设为私有,同时把Shape类型重定义为静态实例的联合类型:
class Shape { // 私有构造函数,禁止外部创建实例 private constructor( public readonly angles: number, public readonly color: string ){} static Triangle = new Shape(3, "red"); static Rectangle = new Shape(4, "blue"); static Circle = new Shape(0, "green"); } // 重定义Shape类型为所有静态实例的联合类型 type Shape = typeof Shape[keyof typeof Shape]; // 此时函数参数直接用Shape即可 function shapeCatchPhrase(shape: Shape): string { switch (shape) { case Shape.Triangle: return "Three is a magic number"; case Shape.Rectangle: return `Are you a ${shape.color} square?`; case Shape.Circle: return `Oh! Look at your ${shape.angles} angles!`; default: return assertNever(shape); } }
原理说明
typeof Shape获取Shape类的静态成员类型(包含Triangle/Rectangle/Circle的键值对类型);keyof typeof Shape获取所有静态成员的键名联合类型("Triangle" | "Rectangle" | "Circle");typeof Shape[keyof typeof Shape]遍历所有静态键,获取对应值的类型,组成最终的实例联合类型;- 当
switch未覆盖所有联合类型分支时,default分支的shape参数类型会不是never,而assertNever要求参数为never,因此触发编译错误,实现了编译期的穷尽匹配检查。
内容的提问来源于stack exchange,提问作者sge
相关产品推荐
相关产品推荐

