You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:25:24