TypeScript泛型:任何接口实现者

问题描述

我对TypeScript中的泛型有疑问。

我有一个名为Obstacle的接口:

import Shape from "./Shape";

interface Obstacle<S extends Shape> {
    readonly type: string;
    readonly shape: S;
}

export default Obstacle;

Obstacle是另一个接口Shape的包装:

interface Shape {
    readonly name: string;
}

export default Shape;

我可以使用这两个接口来创建实现Shape的类,例如RectancleCircle

然后,我创建另一个类,例如分别实现RectangleObstacleCircleObstacle的{​​{1}}或Obstacle<Rectangle>

但是,我的问题是,当我使用它们时,它会遇到一系列障碍(应该包含任何类型的障碍),像这样:

Obstacle<Circle>

我曾尝试放置import Obstacle from "./Obstacle"; interface Data { obstacles: Obstacle<any>[]; /* What should I put here? In the generic parameters list? */ } const DATA: Data = { obstacles: [] }; Obstacle<Shape>[],但不起作用。 另外,我应该能够区分不同类型的障碍,如下所示:

Obstacle<any extends Shape>[]

解决方法

您需要使用discriminated union

type AppObstacle = RectangleObstacle | CircleObstacle

interface Data {
    obstacles: AppObstacle[]; 
}

Playground link

此外,要应用AlekseyL。的建议,如果障碍物只是形状的容器,而没有其他数据或逻辑关联,则可以按以下方式将Shape更改为歧视联合:

interface Shape {
    readonly type: string;
    readonly name: string;
}

interface Rectangle extends Shape {
  type: 'rectangle';
  width: number;
}

interface Circle extends Shape {
  type: 'circle';
  radius: number
}

type AppShape = Rectangle | Circle;

interface Data {
    obstacles: Obstacle[]; 
}

const DATA: Data = {
    obstacles: []
};

function somefunc(): void {
    for(let i: number = 0; i < DATA.obstacles.length; i++) {
        const o = DATA.obstacles[i]; 
        const shape = o.shape;
        switch(shape.type) {
            case 'rectangle':
                shape.width;
                break;
            case 'circle':
                shape.radius;
                break;
        }
    }
}

Playground link