typescript - 在 Typescript 中扩展多个接口或创建新类(多态)
问题描述
我开始在 typescript 中对 API 客户端进行建模,并寻找对数据建模的正确方法的一些说明。API 中的数据模型都共享一组通用属性(抽象),然后每个对象都有更具体的类型。还有一个每个对象将共享的公共元数据集 ($meta),但每个对象的某些值会有所不同。例如:
type Shapes = "Parallelogram" | "Triangle"
type QuadShapes = "Square" | "Trapezoid" | "Rectangle" | "Rhombus" | "Parallelogram"
type ParallelogramShapes = "Square" | "Rectangle" | "Rhombus" | "Parallelogram"
type TriangleShapes = "Isosceles" | "Scalene" | "Equilateral"
interface Meta {
id: number
number_of_sides: number,
type: Shapes,
is_quadrilateral: Boolean,
is_parallelogram: Boolean,
}
interface IShape {
$meta: Meta
}
interface IQuadrilateral extends IShape {
$meta.number_of_sides: number
}
interface IParallelogram extends IQuadrilateral {
$meta.number_of_parallel_sides: number
$meta.type: ParallelogramShapes
}
interface ITriangle extends IShape {
$meta.is_parallelogram: Boolean
$meta.type: TriangleShapes
}
// ISquare should look like:
// {
// $meta: {
// id: 1,
// type: "Parallelogram",
// parallelogram_type: "Square"
// is_parallelogram: true,
// is_quadrilateral: true,
// number_of_sides: 4,
// number_of_parallel_sides: 2
// },
// name: "Some Square"
// color: "Blue"
// }
interface ISquare extends IParallelogram {
// How do i define the $meta node?
$meta:
name: string,
color: string
}
class Square implements ISquare {
$meta: ?
name: string,
color: string
constructor(meta: any, name: string, color: string) {
this.$meta: meta
this.name: name.
this.color: color
}
}
我不确定我是否遗漏了什么,但我遇到的最大问题是如何将$meta
参数建模到接口中。如何以一致、非冗余的方式设置$meta.type
and 。$meta.is_parallelogram
解决方案
我倾向于重构,以便您的Meta
类型形成自己的接口层次结构,并且在它支持的类型上IShape
具有通用性。Meta
首先,我将重写您的类型。请注意,为了保持一致性,我认为您希望Shapes
这样做,TriangleShapes | QuadShapes
因为子类型化要求 ifSquare
实现IShape
该type
属性可分配给IShape
的type
属性。But"Square"
不能分配给"Parallelogram" | "Triangle"
,因为这些是字符串文字类型并且只引用特定的字符串:
type Shapes = TriangleShapes | QuadShapes
type QuadShapes = "Trapezoid" | ParallelogramShapes
type ParallelogramShapes = "Square" | "Rectangle" | "Rhombus" | "Parallelogram"
type TriangleShapes = "Isosceles" | "Scalene" | "Equilateral"
现在我们谈谈Meta
层次结构。我认为,这涉及最少的冗余,因为您只需指定与其超类型的属性相比是新的或更窄的属性:
interface Meta {
id: number
number_of_sides: number,
type: Shapes,
is_quadrilateral: boolean, // Boolean is an object type, use boolean instead
is_parallelogram: boolean, // ditto
}
interface QuadrilateralMeta extends Meta {
number_of_sides: 4;
type: QuadShapes;
is_quadrilateral: true;
}
interface ParallelogramMeta extends QuadrilateralMeta {
type: ParallelogramShapes;
is_parallelogram: true;
}
interface TriangleMeta extends Meta {
type: TriangleShapes;
is_quadrilateral: false;
is_parallelogram: false;
}
interface SquareMeta extends ParallelogramMeta {
type: "Square"
number_of_parallel_sides: 2; // not sure
}
现在我们介绍泛型IShape
:
interface IShape<M extends Meta> {
$meta: M
}
并且ISquare
可以通过指定泛型M
并添加新属性来简明扼要地描述:
interface ISquare extends IShape<SquareMeta> {
name: string;
color: string;
}
最后是你的课:
class Square implements ISquare {
constructor(public $meta: SquareMeta, public name: string, public color: string) { }
}
希望对您有用或给您一些想法。祝你好运!
推荐阅读
- android - onBackPressed() 应用程序未关闭
- php - 如何删除多个连接,执行需要更多时间。如何改善查询结果
- java - Java中将JSON字符串转换为ArrayList的ArrayList
- php - 使用事件名而不是 ID 删除记录
- python - 把函数放在后台
- javascript - d3.js 如何仅将那些节点动态添加到可折叠树中,从数据表中选择
- reactjs - 让图标出现在 React - 三元表达式
- c# - 如何用文本填充和显示数组中的空元素
- python - 将数据框转换为包含字典列表的字典
- hadoop - 在没有 mapred-site.xml 的情况下设置 hadoop mapreduce 大小