Skip to content

extends

主要作用:

  • 继承(JS 中 Class 的 extends 一样)
  • 泛型约束
  • 条件分配

继承

  1. 配合 Class 使用,跟 Java 中的 Class 的继承很像。主要是继承父类的公共方法 和 公共属性
ts
class Animal {
  name: string

  constructor() {}

  sayName() {
    console.log(this.name)
  }
}

class Dog extends Animal {} // 继承的作用
  1. 接口的继承
ts
interface PaginationCommonRequest {
  pageSize: number
  current: number
}

// GetUserPageRequest === {  current: number; pageSize: number; name?: string; }
interface GetUserPageRequest extends PaginationCommonRequest {
  name?: string
}

// 也可以重写某一个属性
// IPaginationCommonRequest === {  current: string; pageSize: number; }
interface IPaginationCommonRequest extends PaginationCommonRequest {
  current: string
}

泛型约束

主要在我们使用泛型的时候,希望传入的泛型必须包含某一个或者多个特定的属性,这时候就可以使用 extends

ts
// T extends { current: number }
function getPaginationCurrent<T extends { current: number }>(pagination: T): number {
  return pagination.current
}

getPaginationCurrent({ current: 1, pageSize: 10 })
getPaginationCurrent({ pageSize: 1 })

image-20230214104008727

在上述例子中 T extends { current: number } 就起到泛型约束的作用,即限制传入的入参 T 必须包含 current 属性

条件分配

对于条件分配很像我们三目运算符,作用也很像

ts
T extends U ? T : U

T 是 U 的一个子集那就返回 T,不然返回 U

  1. 类型判断
  • 接口类型

对于接口,extends 判断的是所有的属性是否相同

ts
interface Pagination {
  pageSize: number
  current: number
  total: number
  pageNumber: number
}

interface PaginationRequest {
  pageSize: number
  current: number
}

interface IPaginationRequest {
  pageSize: number
  current: number
}

type Bool = PaginationRequest extends Pagination ? true : false // false
type Bool1 = IPaginationRequest extends PaginationRequest ? true : false // true
  • type 类型

对于 type,extends 判断的是是否是联合类型的子集

ts
type User = "Admin" | "TL" | "SEAT"
type ConsoleUser = "TL" | "SEAT"

type Bool1 = ConsoleUser extends User ? true : false // true
  1. never

never 是一个特殊的类型,其是所有其他类型的子集,所以

ts
type Bool2 = never extends Pagination ? true : false // true
type Bool3 = never extends number ? true : false // true
type Bool4 = never extends never ? true : false // true
  1. Exclude、Extract、Pick

使用 extends 的条件判断和 never,我们就可以自定义内置的高级类型 Exclude、Extract、Pick

  • Exclude

从 T 中剔除可以赋值给 U 的类型

ts
type Exclude<T, U> = T extends U ? never : T

其中我们有一个特殊的疑惑?

ts
type Exclude1<T, U> = T extends U ? never : T

type IType = "name" | "age" | "address"
type IType2 = "name" | "age" | "sex"

type A = IType extends IType2 ? never : IType // "name" | "age" | "address"
type B = Exclude1<IType, IType2> // "address"

为什么A 和 B的结果是不一样的?

网上有一种解释

ts
type B = Exclude1<IType, IType2> // "address"
// === 
type B = "name" extends IType2 ? never : "name" | "age" extends IType2 ? never : "age"  | "address" extends IType2 ? never : "address"