这是一个简短的例子:
abstract class Base {
private _id: number;
protected set id(value: number) {
this._id = value;
}
protected get id(): number {
return this._id;
}
}
abstract class Mid extends Base {
equals(another: Mid) {
if (this.constructor.name !== another.constructor.name) {
throw TypeError(`Cannot compare ${this.constructor.name} to ${another.constructor.name}`);
}
return this.id === another.id;
}
}
class ChildA extends Mid {
constructor(public name: string) {
super();
}
}
class ChildB extends Mid {
constructor(public name: string) {
super();
}
}
const a = new ChildA('Joe');
const b = new ChildB('John');
a.equals(b); // PREVENT!
我有什么
如果您尝试将ChildA
与ChildB
进行比较,则会引发TypeError
。
我想要什么
我想静态地阻止在不同类之间使用equals方法。如果我不允许在源代码中将Apples与Oranges进行比较,那么我不需要在运行时抛出错误! (也少写一个测试)
请注意Mid
会像Entity
那样非常笼统,而Child
类会像Customer,Order等一样 - 具有商业意义的东西。将客户与订单进行比较是没有意义的,所以我想通过类型在源代码中显示(毕竟,在我看来,这是使用TypeScript的全部意义)。
问题
答案 0 :(得分:0)
您可以通过以下方式约束要从您正在访问的变量类型equal
派生的参数:
abstract class Mid extends Base {
equals<T extends this>(another: T) {
// ...
return this.id === another.id;
}
}
class ChildA extends Mid {
private foo: string;
constructor(public name: string) {
super();
}
}
class ChildAA extends ChildA {
private foo2: string;
constructor( name: string) {
super(name);
}
}
class ChildB extends Mid {
private bar: string;
constructor(public name: string) {
super();
}
}
const a = new ChildA('Joe');
const b = new ChildB('John');
a.equals(b); //Error
a.equals(new ChildAA('')); // Works if you don't want this to work, use equals(another: this) as the signature instead
由于如果ChildA
和ChildB
具有相同的结构,Typescript使用结构类型,上述代码不会阻止您调用equals
,但只要ChildA
和{{ChildB
1}}在结构上不兼容,你会收到错误。
关于你问题的第二部分,你应该评估天气,这会带来更多的悲伤十大好处,这似乎是一个很好的约束,但你应该看看它在实践中是如何运作的。