typescript - 没有宣布所有案件的歧视性工会?
问题描述
考虑一个经典问题,其中可区分联合很有用:
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
(想想包含其他形状的第二个库)。
第一个疑问:我需要该级别的type
字段TShape
来处理任何类型的形状在其非常基本的结构。但是,我还需要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)
请让我知道它是否符合您的要求。
我不确定您是否了解所有可能的联合类型
推荐阅读
- reactjs - 将 for 循环中的项目 onPress 传递给本机反应中的方法/函数
- python - 使用 pymongo 更新并添加更多新的字符串字段到 mongodb 中的对象
- javascript - 我的机器人没有抛出任何错误,但似乎无法连接到 Discord
- powershell - 首次启动时写入输出不返回任何 PSCustomObject
- python - 大熊猫分组后列消失
- java - setText() 使活动崩溃
- javascript - 如何更改来自 React 中道具的输入值?
- sql-server - 使用 insert into 创建的表时,什么会导致查询时间过长?
- c++ - c++ lambda:是否可以通过关闭打开的参数来创建新的 lambda?
- google-maps - Ionic 3 中嵌入的动态长纬度谷歌地图