Skip to main content

深度子类型

假设我们有两个 ,它们使用 extends 具有子类型关系:

¥Assume we have two classes, which have a subtype relationship using extends:

1class Person {2  name: string;3}4class Employee extends Person {5  department: string;6}

在需要 Person 实例的地方使用 Employee 实例是有效的。

¥It's valid to use an Employee instance where a Person instance is expected.

1class Person { name: string }2class Employee extends Person { department: string }3
4const employee: Employee = new Employee();5const person: Person = employee; // OK

但是,如果需要使用包含 Person 实例的对象,则使用包含 Employee 实例的对象是无效的。

¥However, it is not valid to use an object containing an Employee instance where an object containing a Person instance is expected.

1class Person { name: string }2class Employee extends Person { department: string }3
4const employee: {who: Employee} = {who: new Employee()};5const person: {who: Person} = employee; // Error

这是一个错误,因为对象是可变的。employee 变量引用的值与 person 变量引用的值相同。

¥This is an error because objects are mutable. The value referenced by the employee variable is the same as the value referenced by the person variable.

person.who = new Person();

如果我们写入 person 对象的 who 属性,我们还会更改 employee.who 的值,该值被显式注释为 Employee 实例。

¥If we write into the who property of the person object, we've also changed the value of employee.who, which is explicitly annotated to be an Employee instance.

如果我们阻止任何代码通过 person 变量向对象写入新值,则使用 employee 变量将是安全的。Flow 为此提供了语法:

¥If we prevented any code from ever writing a new value to the object through the person variable, it would be safe to use the employee variable. Flow provides a syntax for this:

1class Person { name: string }2class Employee extends Person { department: string }3
4const employee: {who: Employee} = {who: new Employee()};5const person: {+who: Person} = employee; // OK6person.who = new Person(); // Error!

加号 + 表示 who 属性是 协变量。使用协变属性允许我们使用具有该属性的子类型兼容值的对象。默认情况下,对象属性是不变的,允许读取和写入,但它们接受的值受到更多限制。

¥The plus sign + indicates that the who property is covariant. Using a covariant property allows us to use objects which have subtype-compatible values for that property. By default, object properties are invariant, which allow both reads and writes, but are more restrictive in the values they accept.

了解有关 属性差异 的更多信息。

¥Read more about property variance.