Skip to content

类型安全和型变

协变

ts
type Animal = { name: string };
type Dog = { name: string; bark(): void };

// 函数返回 Dog,可以赋值给返回 Animal 的函数
type Getter = () => Animal;
const getDog = (): Dog => ({ name: '旺财', bark() {} });

const getter: Getter = getDog; // ✅ 允许!TypeScript 中函数返回值是协变的

协变 = 越来越具体 → 能替代更抽象的

逆变

ts
type Animal = { name: string };
type Dog = { name: string; bark(): void };

// 函数接收 Animal
type Handler = (animal: Animal) => void;
const handleDog = (dog: Dog) => {
  dog.bark(); // 只能处理 Dog
};

// ❌ TypeScript 默认不允许!但理论上逆变允许这个赋值
// const handler: Handler = handleDog; // ❌ 错误:不能把只接受 Dog 的函数,当成能处理所有 Animal 的函数

双向协变

TypeScript 在非严格模式下,对函数参数允许双向协变,这是为了兼容 JavaScript 的灵活性,但不安全

🔒 在 --strictFunctionTypes 下,函数参数是逆变的,禁止协变赋值。

不变

ts
type Animal = { name: string };
type Dog = { name: string; bark(): void };

const dogs: Dog[] = [
  { name: '旺财', bark() {} },
  { name: '小黑', bark() {} },
];

// const animals: Animal[] = dogs; // ❌ 不允许!尽管 Dog ≼ Animal

因为数组是可变的,如果你把 Dog[] 当作 Animal[],可能会往里面塞 Cat: