likes
comments
collection
share

TS 之 Class 之间的类型兼容性

作者站长头像
站长
· 阅读数 15

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
评论
请登录