TypeScript中如何为Vector类实例指定仅4种状态的类型?
解决TypeScript中Vector实例无法赋值给DirectionVector类型的问题
问题本质
你的Vector类中x和y是number类型,TypeScript会认为这些属性可以被修改为任意数值;而DirectionVector是字面量类型的联合,要求x和y必须是精确的1/-1/0。两者类型约束不匹配,所以即使实例值符合要求,TypeScript也会报错。
解决方案
方案1:用工厂函数生成合规的方向向量实例
给Vector的属性加上readonly确保不可修改,再通过工厂函数做类型和运行时双重校验,避免非法赋值:
class Vector { readonly x: number = 0; readonly y: number = 0; constructor(x: number, y: number) { this.x = x; this.y = y; } } type DirectionVector = { x: 1; y: 0; } | { x: -1; y: 0; } | { x: 0; y: 1; } | { x: 0; y: -1; }; // 工厂函数:仅生成符合方向向量规则的实例 function createDirectionVector(x: 1 | -1 | 0, y: 1 | -1 | 0): DirectionVector { // 运行时校验,防止传入合法类型但不符合规则的组合(比如x=1,y=1) const validCombos = new Set([`1,0`, `-1,0`, `0,1`, `0,-1`]); if (!validCombos.has(`${x},${y}`)) { throw new Error('输入的坐标不符合方向向量规则'); } return new Vector(x, y) as DirectionVector; } // 合法:类型和值都符合要求 const rightVec = createDirectionVector(1, 0); // 类型错误:参数不允许传入5 const invalidVec = createDirectionVector(5, 3);
方案2:让DirectionVector成为Vector的子类型
调整DirectionVector的定义,使其继承Vector类型,再用类型守卫做校验:
class Vector { x: number = 0; y: number = 0; constructor(x: number, y: number) { this.x = x; this.y = y; } } // 定义DirectionVector为Vector的子类型,同时约束x/y的字面量值 type DirectionVector = Vector & ( { x: 1; y: 0; } | { x: -1; y: 0; } | { x: 0; y: 1; } | { x: 0; y: -1; } ); // 类型守卫:判断Vector实例是否符合DirectionVector规则 function isDirectionVector(vec: Vector): vec is DirectionVector { return (vec.x === 1 && vec.y === 0) || (vec.x === -1 && vec.y === 0) || (vec.x === 0 && vec.y === 1) || (vec.x === 0 && vec.y === -1); } // 使用示例 const testVec = new Vector(1, 0); if (isDirectionVector(testVec)) { // 此处testVec会被TypeScript推断为DirectionVector类型 console.log('合法的方向向量:', testVec.x, testVec.y); } // 直接赋值需要类型断言,同时建议配合运行时校验 const upVec = new Vector(0, 1) as DirectionVector;
方案3:用枚举简化方向向量定义
如果不需要Vector类的额外方法,用枚举+工具函数实现会更简洁:
// 定义方向枚举 enum Direction { Right, Left, Up, Down, } // 定义方向向量类型 type DirectionVector = { x: 1 | -1 | 0; y: 1 | -1 | 0; }; // 根据枚举返回对应的方向向量 function getDirectionVector(dir: Direction): DirectionVector { switch (dir) { case Direction.Right: return { x: 1, y: 0 }; case Direction.Left: return { x: -1, y: 0 }; case Direction.Up: return { x: 0, y: 1 }; case Direction.Down: return { x: 0, y: -1 }; } } // 使用示例 const downVec = getDirectionVector(Direction.Down);
内容的提问来源于stack exchange,提问作者MrCano369x
相关产品推荐
相关产品推荐

