ts中extends的作用

54 阅读2分钟

🧩 一、在 类(class) 中:继承父类

✅ 用法:子类继承父类的属性和方法

class Animal {
  move() {
    console.log('Moving...');
  }
}

class Dog extends Animal {
  bark() {
    console.log('Woof!');
  }
}

const dog = new Dog();
dog.move(); // ✅ 从 Animal 继承
dog.bark(); // ✅ 自己定义

理解:

class Dog extends Animal
意思是「Dog 是 Animal 的子类」,拥有 Animal 的能力。


🧠 补充:super 关键字

当子类重写构造函数或方法时,可以通过 super 调用父类的实现:

class Animal {
  constructor(public name: string) {}
}

class Dog extends Animal {
  constructor(name: string, public breed: string) {
    super(name); // 调用父类构造函数
  }
}

🧠 二、在 泛型(Generics) 中:类型约束(extends T)

这部分更重要,也是面试重点。


✅ 用法 1:限制泛型的取值范围

function getLength<T extends { length: number }>(arg: T) {
  return arg.length;
}

getLength('hello'); // ✅ string 有 length
getLength([1, 2, 3]); // ✅ 数组有 length
getLength(42); // ❌ number 没有 length

解释:

T extends { length: number }
表示泛型参数 T 必须“至少拥有一个 length 属性”。


✅ 用法 2:继承类型或交叉类型

interface Person {
  name: string;
}

interface Student extends Person {
  grade: number;
}

const s: Student = { name: 'Alice', grade: 90 };

解释:

Student 继承了 Person 的属性,相当于 Student = Person & { grade: number }


✅ 用法 3:泛型条件判断(条件类型)

extends 在条件类型中表示 “是否可赋值” 的判断。

type IsString<T> = T extends string ? true : false;

type A = IsString<'abc'>; // true
type B = IsString<number>; // false

👉 T extends string 表示「T 是否可以赋值给 string」。

这是很多 TS 内置工具类型(如 ExcludeExtract)的核心机制。


✅ 用法 4:联合类型的分发(Distributive)

在条件类型中,extends 对联合类型会自动“分发”:

type T1 = 'a' | 'b' | 'c';
type ExcludeA<T> = T extends 'a' ? never : T;

type R = ExcludeA<T1>; // 'b' | 'c'

解释:

T extends 'a' 会对联合类型 'a' | 'b' | 'c' 分别计算一次,
'a' → never, 'b' → 'b', 'c' → 'c'。

这就是内置类型 Exclude<T, U> 的底层原理。


✅ 用法 5:限制函数参数类型

function merge<T extends object, U extends object>(a: T, b: U) {
  return { ...a, ...b };
}

merge({ name: 'Tom' }, { age: 20 }); // ✅
merge(123, 456); // ❌ number 不是 object

✅ 用法 6:提取子类型(infer 搭配 extends)

这是 TS 高级类型中最常用的组合:

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type Fn = () => number;
type Result = ReturnType<Fn>; // number

解释:

  • extends (...args: any[]) => infer R
    → 表示 T 必须是函数类型;
  • infer R 表示“推断出返回值类型 R”。

✅ 三、总结对比

语境写法意义
类继承class B extends AB 继承 A 的属性和方法
泛型约束<T extends U>限制 T 必须满足 U 的结构
条件类型T extends U ? X : Y判断 T 是否可赋值给 U
接口继承interface B extends AB 拥有 A 的所有属性
infer 结合T extends (...) => infer R从类型结构中提取部分类型

✅ 四、记忆口诀

extends 的本质是“约束 + 继承 + 判断”

  • 类中:继承行为
  • 泛型中:限制范围
  • 条件类型中:类型判断

🎯 一句话总结

extends 在 TypeScript 中相当于「类型世界里的 <=」。

它表示:左边类型能否赋值给右边类型
左边类型是否是右边的子类型