逆变(Contravariance)
- 场景:函数参数类型的兼容性。当一个函数期望接收一个更具体类型的参数,但实际传入一个更宽泛类型的函数时,逆变可以确保类型安全。
- 代码示例:
interface Contravariant<T> {
(arg: T): void;
}
// 定义一个具体类型的函数
function handleString(str: string): void {
console.log(str);
}
// 定义一个宽泛类型的函数
function handleAny(arg: any): void {
console.log(arg);
}
// 逆变示例,这里宽泛类型函数可以赋值给具体类型函数的位置
let stringHandler: Contravariant<string> = handleAny;
- 类型安全解释:在逆变场景中,因为
handleAny
可以处理任何类型,那么它一定可以处理string
类型。如果反过来将handleString
赋值给期望Contravariant<any>
的地方就会报错,因为handleString
不能处理所有类型,只能处理string
类型,这保证了类型安全。
协变(Covariance)
- 场景:函数返回值类型的兼容性。当一个函数期望返回一个更宽泛类型的值,但实际返回一个更具体类型的值时,协变可以确保类型安全。
- 代码示例:
interface Covariant<T> {
(): T;
}
// 定义一个返回具体类型的函数
function getString(): string {
return 'Hello';
}
// 定义一个返回宽泛类型的函数
function getAny(): any {
return 'Hello';
}
// 协变示例,具体类型函数可以赋值给宽泛类型函数的位置
let anyGetter: Covariant<any> = getString;
- 类型安全解释:在协变场景中,因为
getString
返回string
类型,string
是any
的子类型,所以可以将getString
赋值给期望返回any
类型的函数位置。如果反过来将getAny
赋值给期望Covariant<string>
的地方就会报错,因为getAny
返回的不一定是string
类型,这保证了类型安全。