如何从映射变量中获取具体类型? [英] How to get concrete type from mapping variable?

查看:0
本文介绍了如何从映射变量中获取具体类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

const enum ShapeType {
  Circle,
  Rectangle
}

class Shape {
  constructor(public shapeType: ShapeType) {}
}

class Circle extends Shape {
  constructor(public x: number, public y: number, public r: number) {
    super(ShapeType.Circle);
  }
}

class Rectangle extends Shape {
  constructor(public x: number, public y: number, public w: number, public h: number) {
    super(ShapeType.Rectangle);
  }
}

function handleRectangleRectangleCollision(r1: Rectangle, r2: Rectangle) {
  return Helpers.doRectanglesCollide(r1.x, r1.y, r1.w, r1.h, r2.x, r2.y, r2.w, r2.h)
}

function handleRectangleCircleCollision(r: Rectangle, c: Circle) {
  return Helpers.circleRectangleCollision(c.x, c.y, c.r, r.x, r.y, r.w, r.h);
}

function handleCircleCircleCollision(c1: Circle, c2: Circle) {
  return Helpers.circlesCollide(c1.x, c1.y, c1.r, c2.x, c2.y, c2.y);
}

function handleCircleRectangleCollision(c: Circle, r: Rectangle) {
  return Helpers.circleRectangleCollision(c.x, c.y, c.r, r.x, r.y, r.w, r.h);
}

export let colliderMapping = {
  [ShapeType.Rectangle]: {
    [ShapeType.Rectangle]: handleRectangleRectangleCollision,
    [ShapeType.Circle]: handleRectangleCircleCollision
  },
  [ShapeType.Circle]: {
    [ShapeType.Circle]: handleCircleCircleCollision,
    [ShapeType.Rectangle]: handleCircleRectangleCollision
  }
}

function doShapesCollide(s1: Shape, s2: Shape) {
  let colliderFn = colliderMapping[s1.shapeType][s2.shapeType];

  return colliderFn(s1, s2);
}

我在最后一个上收到一个错误:

return colliderFn(s1, s2);

Argument of type 'Shape' is not assignable to parameter of type 'Rectangle & Circle'.
  Type 'Shape' is missing the following properties from type 'Rectangle': x, y, w, h

我理解为什么会出现这个错误(我想),但我不知道如何解决它。我基本上是想通过一个映射变量来实现一种简洁的双重分派方式,这样形状的每个组合都将返回一个有效的函数,我可以调用该函数来查看它们是否发生冲突。

有没有办法做到这一点?如果是,如何?

推荐答案

我注意到handleRectangleCircleCollisionhandleCircleRectangleCollision做的是相同的事情,但只是更改了传递参数的顺序。

function handleRectangleCircleCollision(r: Rectangle, c: Circle) {
  return Helpers.circleRectangleCollision(c.x, c.y, c.r, r.x, r.y, r.w, r.h);
}

function handleCircleRectangleCollision(c: Circle, r: Rectangle) {
  return Helpers.circleRectangleCollision(c.x, c.y, c.r, r.x, r.y, r.w, r.h);
}

您还将类和继承(OOP方法)与类外部的函数一起使用。

我试图减少代码并使其保持简单。 这里有一个利用打字机保护装置的解决方案。我还用交叉点类型替换了类。

type Point = { x: number; y: number; }
type Rectangle = { w: number; h: number; } & Point
type Circle = { r: number } & Point
type Shape = Rectangle | Circle

function isCircle(shape: Shape): shape is Circle {
  return 'r' in shape;
}  
function handleShapeCollision(shapeA: Shape, shapeB: Shape) {
  if (isCircle(shapeA)) 
  return handleCircleCollision(shapeA, shapeB);
  return handleRectangleCollision(shapeA, shapeB);
}
function handleCircleCollision(circle: Circle, shape: Shape) {
  if (isCircle(shape)) 
  return Helpers.circlesCollide(circle.x, circle.y, circle.r, shape.x, shape.y, shape.y);
  return Helpers.circleRectangleCollision(circle.x, circle.y, circle.r, shape.x, shape.y, shape.w, shape.h);
}
function handleRectangleCollision(r: Rectangle, shape: Shape) {
  if (isCircle(shape)) 
  return Helpers.circleRectangleCollision(shape.x, shape.y, shape.r, r.x, r.y, r.w, r.h);
  return Helpers.doRectanglesCollide(r.x, r.y, r.w, r.h, shape.x, shape.y, shape.w, shape.h)
}

这里是TypescriptPlayground。尽情玩耍吧。

这篇关于如何从映射变量中获取具体类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆