全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-21 8 分钟 ✍️ juanwangdev

TypeScript 类型兼容深层逻辑

TypeScript 使用结构化类型系统,类型兼容性取决于结构而非名称,下面梳理深层兼容规则。

结构化类型 vs 名义类型

结构化类型(TypeScript)

TypeScript
interface A { x: number; y: string; }
interface B { x: number; y: string; }

let a: A = { x: 1, y: "hello" };
let b: B = a;  // ✅ 结构相同,可赋值

名义类型(Java/C#)

Java
// Java 中即使结构相同,不同类型也无法赋值
interface A { int x; String y; }
interface B { int x; String y; }
// A a = new B();  // ❌ 类型不同

对象兼容性规则

多余属性检查

仅在字面量赋值时生效:

TypeScript
interface User { name: string; }

// 字面量直接赋值:严格检查
const u: User = { name: "Alice", age: 25 };  // ❌ age 不存在

// 通过变量赋值:允许
const data = { name: "Alice", age: 25 };
const u2: User = data;  // ✅ 结构兼容(目标有更多属性可以)

子类型兼容

目标类型的每个属性在源类型中都必须存在且兼容:

TypeScript
interface Base { id: string; }
interface Extended extends Base { name: string; }

let base: Base;
let extended: Extended = { id: "1", name: "Alice" };

base = extended;  // ✅ Extended 包含 Base 所有属性
// extended = base;  // ❌ Base 缺少 name

函数兼容性

参数数量

源函数参数可以多于目标函数,但不能少于:

TypeScript
let fn1 = (a: number, b: number) => {};
let fn2 = (a: number) => {};

fn1 = fn2;  // ✅ 目标参数少可以(忽略多余参数)
// fn2 = fn1;  // ❌ 源参数多,调用时可能缺少参数

参数类型协变与逆变

TypeScript 默认函数参数双向协变(strictFunctionTypes 开启后变为逆变):

TypeScript
// 开启 strictFunctionTypes 后
class Animal { run() {} }
class Dog extends Animal { bark() {} }

let fn1 = (a: Animal) => {};
let fn2 = (a: Dog) => {};

fn1 = fn2;  // ❌ Dog 是 Animal 子类型,参数应逆变
fn2 = fn1;  // ✅ 接受 Animal 可以传入 Dog

返回值协变

返回值必须是目标返回值的子类型:

TypeScript
class Animal {}
class Dog extends Animal {}

let fn1 = () => new Animal();
let fn2 = () => new Dog();

fn1 = fn2;  // ✅ Dog 是 Animal 子类型
// fn2 = fn1;  // ❌ Animal 不是 Dog 子类型

泛型兼容性

类型参数兼容

TypeScript
interface Container<T> {
  value: T;
}

let c1: Container<string | number>;
let c2: Container<string>;

c1 = c2;  // ✅ string 是 string|number 子类型
// c2 = c1;  // ❌ string|number 不一定是 string

泛型函数兼容

TypeScript
type Fn<T> = (arg: T) => T;

let f1: Fn<string | number>;
let f2: Fn<string>;

f1 = f2;  // ✅(返回值协变,参数逆变)

枚举兼容性

枚举与数字双向兼容:

TypeScript
enum Status { Active = 1, Inactive = 2 }

let s: Status = Status.Active;
let n: number = 1;

s = n;  // ✅ 数字可赋值给枚举
n = s;  // ✅ 枚举可赋值给数字

不同枚举间不兼容:

TypeScript
enum Color { Red = 0, Green = 1 }
enum Size { Small = 0, Large = 1 }

let c: Color = Color.Red;
// let sz: Size = c;  // ❌ 不同枚举不兼容

要点总结

  • TypeScript 使用结构化类型,结构相同即可赋值,不关心名称
  • 字面量赋值时有多余属性检查,变量赋值时不检查
  • 函数参数默认协变(strictFunctionTypes 开启后逆变),返回值协变
  • 泛型兼容性取决于类型参数的协变/逆变声明
  • 枚举与数字双向兼容,不同枚举间不兼容

📝 发现内容有误?点击此处直接编辑

← 上一篇 TypeScript 自定义复杂工具类型
下一篇 → TypeScript 编译原理
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库