1. 子类型是父类的超集,因为子类型继承了父类,因为子类型属性更多
举例:
interface Animal {
age: number
}
interface Dog extends Animal {
dark(): void
}
所以在可以赋值性方面,子可以赋值父,但父不可以赋值子
举例
let animal: Animal
let dog: Dog
animal = dog // ✅ok
dog = animal // ❌error! animal 实例上缺少属性 'dark'
2. 逆变(函数参数)
有两个函数
let visitAnimal = (animal: Animal) => void;
let visitDog = (dog: Dog) => void;
let visitAnimal = (animal: Animal) => {
animal.age
}
let visitDog = (dog: Dog) => {
dog.age
dog.bark()
}
错误示例
这个时候 没有dark 方法
visitAnimal = visitDog
let animal = { age: 5 }
visitAnimal(animal) // ❌
正确用例
visitDog = visitAnimal
let animal = { age: 5,dark: () => {} }
visitDog(animal)
当然,在 TypeScript 中,由于灵活性等权衡,对于函数参数默认的处理是 双向协变
的。也就是既可以 visitAnimal = visitDog
,也可以 visitDog = visitAnimal
。在开启了 tsconfig
中的 strictFunctionType
后才会严格按照 逆变
来约束赋值关系。