Skip to content

泛型允许同一个函数或类支持多种数据类型,极大提升了代码的灵活性和复用性

泛型之前

typescript
// 函数重载
function log(value: string): string
function log(value: number): number
function log(value: string[]): string[]
function log(value: any) {
  return value
}

// 联合类型
function log(value: string | number | string[]): string | number | string[] {
  return value
}

// any类型
function log(value: any) {
  return value
}

使用泛型

不预先确定的类型,具体类型在使用时才能确定 优势: 类型T不需要预先指定,相当于any,保证输入参数和返回值的一致性 定义方式: 未知类型使用<T>表示,参数类型,返回值类型均为T

泛型声明

typescript
function log<T>(value: T): T {
  return value
}

泛型调用

typescript
// 1. 直接指定T的具体类型进行调用
log<string[]>(['a', 'b'])

// 2. 利用TS类型推断,省略类型参数
log(['a', 'b'])

使用泛型定义函数类型

泛型不仅可以定义函数,还可以定义函数类型 定义方式: 类型别名type关键字 + 名称,可定义一个泛型函数类型

typescript
// 泛型声明
function log<T>(value: T): T {
  return value
}

// 使用泛型定义函数类型Log
type Log = <T>(value: T) => T

// 声明变量myLog为Log类型
let myLog: Log = log

泛型接口

泛型也可以用于接口中,对接口中的函数或成员进行约束 使用泛型约束接口中的函数:和类型别名的定义方式是完全等价的。仅仅约束了一个函数

typescript
// 使用泛型约束接口中的函数
interface Log {
  <T>(value: T): T
}

还可以使用泛型来约束接口的其他成员 注意:当泛型变量约束了整个接口后,实现时必须指定一个具体类型

typescript
interface ResponseData<T> {
  resCode: number
  resData: T
  message: string
}

let arrayResult: ResponseData<string[]> = {
  resCode: 0,
  resData: ['1', '2'],
  message: '',
}

使用泛型约束类的成员

定义一个泛型类,将泛型变量放在类名称之后,就可以约束类的所有成员

typescript
// 泛型类-约束所有类的成员了
class Log<T> {
  run(value: T) {
    return value
  }
}

// 实例化类时,如果指定T的类型,则只能传入指定类型
let log = new Log<number>()
log.run(1)

// 如果不指定T的类型,则可以传入所有类型
let log = new Log()
log.run('test Log')

注:泛型不能用于类的静态成员

image.png

泛型约束

使用泛型的情况下,如果需要对T.length进行输出,则错误提示:

image.png

改进: 由于T继承了Length接口,所以类型检查不再报错 但此时T也受到了一定约束,要求必须是具length属性。如数、字符串、对象等

typescript
// 定义length属性接口
interface Length {
  length: number
}

// 类型T继承Length接口
function log<T extends Length>(value: T): T {
  console.log(value.length)
  return value
}

泛型的好处

函数和类可以轻松地支持多种类型,增强程序的控制性 不必写多余函数重载,冗长的联合类型声明,增强代码可读性 灵活控制类型之间的约束

typescript
class DLog<T> {
  run(value: T) {
    console.log(value)
    return value
  }
}
let log1 = new DLog<number>()
log1.run(1)
// log1.run('1')
let log2 = new DLog()
log2.run({ a: 1 })
log2.run('1')

interface Length {
  length: number
}
function Dlog<T extends Length>(value: T): T {
  console.log(value, value.length)
  return value
}
Dlog([1])
Dlog('123')
Dlog({ length: 1 })

学习笔记出自于梁宵老师课程

Layout Switch

Adjust the layout style of VitePress to adapt to different reading needs and screens.

Expand all
The sidebar and content area occupy the entire width of the screen.
Expand sidebar with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Expand all with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Original width
The original layout width of VitePress

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.

Spotlight

Highlight the line where the mouse is currently hovering in the content to optimize for users who may have reading and focusing difficulties.

ONOn
Turn on Spotlight.
OFFOff
Turn off Spotlight.