歧视工会而不公布所有案例?



考虑一个经典问题,在这个问题中区分联合很有用:

type TShape = {
type: string;
}
type TDrawing = {
shapes: Array<TShape>;
}
const TypeRect = "rect";
type TRectangle = TShape & {
type: typeof TypeRect;    //correct?
width: number;
height: number;
}
const TypeCircle = "cricle";
type TCircle = TShape & {
type: typeof TypeCircle;  //correct?
radius: number;
}

和更多

然后是上述定义的一个应用:

const drawing: TDrawing = {
shapes: [
{ type: TypeRect, width: 2, height: 3 },    //error
{ type: TypeCircle, radius: 5 },            //error
{ type: TypeRect, width: 10, height: 5 },   //error
]
}

function getCircles(drawing: TDrawing): Array<TCircle> {
const a: Array<TCircle> = [];
for (const shape of drawing.shapes) {
if (shape.type === TypeCircle) {
a.push(shape);    //error
}
}
return a;
}

现在,考虑TShape派生的类型对于定义TShape的库来说不一定是已知的(考虑包含其他形状的第二个库)。

第一个疑问:我需要TShape级别的type场来处理任何一种形状的最基本结构。然而,我还需要type专门化来区分实际的形状。在派生类型中重新定义字段是否正确?

第二个问题:我找不到一种方法让编译器推断出正确的类型,无论是在数组定义中,还是在循环中。有没有一种方法可以同时解决这两个问题?

我想你在寻找这样的东西:


type TShape = {
type: string;
id: string;
}
type TRectangle = TShape & {
type: "rect";
width: number;
height: number;
}
type TCircle = TShape & {
type: "circle";
radius: number;
}
type Circle = 'circle'
type Rect = 'rect'

type Shapes = TRectangle | TCircle
type TDrawing = {
shapes: Array<Shapes>;
}

type TPolygon = TShape & {
edgeCount: number;
}
const drawing: TDrawing = {
shapes: [
{ type: 'rect', width: 2, height: 3, id: '1' },    //ok
{ type: 'circle', radius: 5, id: '2' },            //ok
{ type: 'rect', width: 10, height: 5, id: 2 },   // expected error, id should be string
{ type: 'circle' }, // expected error, no id, no raduis
{ type: 'circle', edgeCount: 8 }, // expected error, you don't allow extra properties
]
}
const requiredProps = ['id']
const hasProperties = <T, P extends string>(obj: T, props: P[]) => props.every(prop => Object.prototype.hasOwnProperty.call(obj, prop))
const isCircle = (shape: Shapes): shape is TCircle => shape.type === 'circle' && hasProperties(shape, ['radius', ...requiredProps])

const isRect = (shape: Shapes): shape is TRectangle => shape.type === 'rect' && hasProperties(shape, ['width, height', ...requiredProps])
const getCircles = (drawing: TDrawing): Array<TCircle> => drawing.shapes.filter(isCircle)
const getRect = (drawing: TDrawing): Array<TRectangle> => drawing.shapes.filter(isRect)

请告诉我是否符合你的要求。

我不确定你是否知道前面所有可能的联合类型

操场上联系

最新更新