TS 之 Class 之间的类型兼容性
Class 之间的类型兼容对比方式,与纯对象和接口的对比方式是类似的。但 class 类型与这两者存在不同的是,它同时拥有实例类型和静态类型两种场景。但是 class 之间做类型对比时,只会对它们的实例成员类型进行对比。Class 的静态成员类型和构造函数类型不会影响 class 类型之间的兼容性
在下面示例中,两个 class 都拥有一个相同类型的属性feet: number
。但是它们构造函数的参数个数和类型明显都是不一样的,Animal 拥有两个参数,Size 只拥有一个参数
但并不影响两个 class 实例之间的类型兼容性
class Animal {
feet: number;
constructor(name: string, numFeet: number) {}
}
class Size {
feet: number;
constructor(numFeet: number) {}
}
let a: Animal;
let s: Size;
a = s; // OK
s = a; // OK
Class 的 private 成员和 protected 成员
Class 的 private 成员和 protected 成员会影响它们之间的类型兼容性
也就是说,class 之间进行类型对比时,双方的 private 和 protected 成员必须都必须要继承于同一个父类才是互相兼容的
例如下面实例中,Parent 中定义了一个 private name = 'cxc'
,Animal 和 Size 都继承了它。这样并不会影响两个 class 的实例类型的兼容性:
class Parent {
private name = 'cxc'
}
class Animal extends Parent {
feet: number = 1;
constructor(name: string, numFeet: number) {
super()
}
}
class Size extends Parent {
feet: number = 2;
constructor(numFeet: number) {
super()
}
}
let a: Animal = new Animal('cxc', 1);
let s: Size = new Size(2);
a = s; // OK
s = a; // OK
但是,如果两个 Class 继承的是不同父类,即使继承的两个父类的结构和类型是完全相同的,那么两个子类的实例类型也是不兼容的
下面示例中,Animal 和 Size 继承了不同的父类,虽然两个父类都定义了private name = 'cxc'
,但两个子类的实例类型仍然是互不兼容的:
class Parent1 {
private name = 'cxc'
}
class Parent2 {
private name = 'cxc'
}
class Animal extends Parent1 {
feet: number = 1;
constructor(name: string, numFeet: number) {
super()
}
}
class Size extends Parent2 {
feet: number = 2;
constructor(numFeet: number) {
super()
}
}
let a: Animal = new Animal('cxc', 1);
let s: Size = new Size(2);
a = s; // OK
s = a; // OK
Type 'Size' is not assignable to type 'Animal'.
Types have separate declarations of a private property 'name'.
Type 'Animal' is not assignable to type 'Size'.
Types have separate declarations of a private property 'name'.
那如果,把这两个父类的 private 修饰符去掉,这两个 Class 的实例类型也就互相兼容了
转载自:https://juejin.cn/post/7208036915014680634