如何读取联合类型中其中一个类型的属性?

interface Square {
  kind: 'square';
  sideLength: number;
}

interface Rectangle {
  kind: 'rectangle';
  width: number;
  height: number;
}

interface Circle {
  kind: 'circle';
  radius: number;
}

type Shape = Square | Rectangle | Circle;

function printArea(shape: Shape) {
  switch (shape.kind) {
    case 'square':
      console.log('正方形的面积:', shape.sideLength * shape.sideLength);
      break;
    case 'rectangle':
      console.log('矩形的面积:', shape.width * shape.height);
      break;
    case 'circle':
      console.log('圆形的面积:', Math.PI * shape.radius * shape.radius);
      break;
  }
}

以上代码使用了 kind 属性识别了不同的类型,假如因为某些条件不能设置类似 kind 这样的属性,那怎么识别不同的类型让代码不出现类型警告?

阅读 613
avatarAI BotBETA

如果你不能在联合类型中设置像 kind 这样的属性来区分不同的类型,并且想要避免类型警告,你可以使用 TypeScript 的类型守卫(Type Guards)或者类型断言(Type Assertions)。但是,最好的做法通常是能够在类型定义中明确区分它们,因为这有助于 TypeScript 编译器提供类型安全和智能提示。

使用类型守卫

类型守卫是一种特殊的表达式,它执行运行时检查以确保某个值符合特定类型。在 TypeScript 中,你可以通过函数、in 操作符、typeof 操作符或 instanceof 操作符等方式来实现类型守卫。

但是,在你的案例中,由于你没有 kind 属性,你可能需要依赖于其他逻辑或结构来区分类型,这通常不是理想的做法。然而,假设你可以根据其他属性或结构来推断类型,你可以这样写:

function isSquare(shape: Shape): shape is Square {
  // 假设这里有一个逻辑可以判断是否为 Square
  // 注意:这只是一个示例,实际上你需要一个有效的逻辑
  return false; // 示例,应替换为实际逻辑
}

function isRectangle(shape: Shape): shape is Rectangle {
  // 假设这里有一个逻辑可以判断是否为 Rectangle
  return false; // 示例,应替换为实际逻辑
}

function printArea(shape: Shape) {
  if (isSquare(shape)) {
    console.log('正方形的面积:', shape.sideLength * shape.sideLength);
  } else if (isRectangle(shape)) {
    console.log('矩形的面积:', shape.width * shape.height);
  } else {
    // 假设剩余的为 Circle
    console.log('圆形的面积:', Math.PI * shape.radius * shape.radius);
  }
}

使用类型断言

如果你确定某个值属于某个类型,但 TypeScript 编译器无法推断出来,你可以使用类型断言来告诉编译器你的意图。但请注意,这可能会引入运行时错误,因为断言的正确性是由你保证的,而不是由 TypeScript 保证的。

function printArea(shape: Shape) {
  if ((shape as Square).sideLength !== undefined) {
    console.log('正方形的面积:', (shape as Square).sideLength * (shape as Square).sideLength);
  } else if ((shape as Rectangle).width !== undefined && (shape as Rectangle).height !== undefined) {
    console.log('矩形的面积:', (shape as Rectangle).width * (shape as Rectangle).height);
  } else {
    console.log('圆形的面积:', Math.PI * (shape as Circle).radius * (shape as Circle).radius);
  }
}

然而,这种方法依赖于运行时检查,并不如使用类型守卫那样清晰和类型安全。

结论

在没有像 kind 这样的属性来区分类型的情况下,你可能需要依赖更复杂的逻辑来推断类型,或者重新考虑你的类型设计以包含这样的区分属性。如果可能的话,添加一个 kind 属性或类似的属性来明确区分类型通常是更好的选择。

1 个回答

可以通过使用类型保护(Type Guards)来识别不同的类型,而不依赖于 kind 属性。你可以使用 in 操作符、typeof 操作符或 instanceof 操作符来实现类型保护。下面写了一个 in 操作符的例子:

interface Square {
  sideLength: number;
}

interface Rectangle {
  width: number;
  height: number;
}

interface Circle {
  radius: number;
}

type Shape = Square | Rectangle | Circle;

function printArea(shape: Shape) {
  if ('sideLength' in shape) {
    console.log('正方形的面积:', shape.sideLength * shape.sideLength);
  } else if ('width' in shape && 'height' in shape) {
    console.log('矩形的面积:', shape.width * shape.height);
  } else if ('radius' in shape) {
    console.log('圆形的面积:', Math.PI * shape.radius * shape.radius);
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏