《六》TypeScript 中的泛型

泛型:宽泛的类型,其实就是类型的参数化,让类型像参数一样,不预先指定,而是在使用的时候再让别人传入进来。

在定义函数、类或者接口时,如果遇到类型不明确的时候,就可以使用泛型。

平常开发中可能会用到一些名称的缩写:

  1. T:Type 的缩写,类型。
  2. K、V:key 和 value 的缩写,键值对。
  3. E:Element 的缩写,元素。
  4. O:Object 的缩写,对象。

泛型函数:

定义函数时,在函数名的后面加上 <通用的任意命名的类型名称>,然后再将类型定义为参数的类型;调用函数时,在函数名的后面加上 <具体的实际的类型名称>

例如:定义一个函数,参数接收什么,返回值就返回什么。

// 1. 没有给参数 args 定义类型,默认是 any
function fn (args) {
  return args
}

// 2. 返回值的类型就也是 any。但这样其实就是没有做类型检测
const res1 = fn('Lee')
const res2 = fn(18)

《六》TypeScript 中的泛型_第1张图片

// 3. 给参数 args 定义联合类型
function fn2 (args: string | number) {
  return args
}

// 4. 返回值的类型就也是联合类型。但实际想要的结果是传入什么类型的参数,就返回什么类型的返回值
const res3 = fn2('Lee')
const res4 = fn2(18)

《六》TypeScript 中的泛型_第2张图片

// 使用泛型来实现:argsType 就相当于是一个变量,记录了本次调用参数的类型。所以在函数的整个执行过程中,都能一直保留着参数的类型
// 2. 接收类型
// 3. 将其定义为参数的类型
function fn3 (args: argsType) {
  return args
}

// 1. 将类型传入
const res5 = fn3('Lee')
const res6 = fn3(18)

《六》TypeScript 中的泛型_第3张图片

大部分情况,调用函数时,可以省略不传递类型,因为 TypeScript 会根据传递的参数进行类型推断。但是也有可能会推断错误,此时就需要手动传递类型了。

function fn (args: argsType) {
  return args
}

// 可以省略不传递类型,TypeScript 会根据传递的参数进行类型推断
let res1 = fn('Lee') // 使用 let 会推断出 string 类型
const res2 = fn(18) // 使用 cont 会直接推断成更加具体的字面量类型

泛型函数支持给类型指定默认值。

function fn (args: argsType ) {
  return args
}

let res = fn('Lee')

泛型函数支持传入多个泛型。

function fn (args1: args1Type, args2: args2Type ) {
  return {args1, args2}
}

const res = fn('Lee', 18)

泛型类:

在定义类的时候也可以使用泛型。

定义类时,在类名的后面加上 <通用的任意命名的类型名称>,然后再将类型定义为属性的类型;调用类时,在类名的后面加上 <具体的实际的类型名称>

class Point {
  constructor(public x: Type, public y: Type) {}
}

const p1 = new Point(10, 20)
const p2 = new Point('10', '20')

大部分情况,调用类时,可以省略不传递类型,因为 TypeScript 会根据传递的参数进行类型推断。但是也有可能会推断错误,此时就需要手动传递类型了。

泛型类支持给类型指定默认值。

泛型类也支持传入多个泛型。

泛型接口:

在定义接口的时候也可以使用泛型。

定义接口时,在接口名的后面加上 <通用的任意命名的类型名称>,然后再将类型定义为属性的类型;调用接口时,在接口名的后面加上 <具体的实际的类型名称>

interface PersonInterface {
  name: Type,
  age: number,
  hobby: Type,
}

const p1: PersonInterface = {
  name: 'Lee',
  age: 18,
  hobby: '吃',
}

const p2: PersonInterface = {
  name: true,
  age: 18,
  hobby: false,
}

泛型接口中,TypeScript 无法进行类型推断,必须明确传递类型。除非指定默认值的话,就可以不明确传递类型了。

《六》TypeScript 中的泛型_第4张图片

// 指定类型的默认值
interface PersonInterface {
  name: Type,
  age: number,
  hobby: Type,
}

const p: PersonInterface = {
  name: 'Lee',
  age: 18,
  hobby: '吃',
}

泛型接口也支持传入多个泛型。

泛型约束:

泛型约束:其实就是给泛型添加一个约束。通过 extends 关键字继承某个类型,表示泛型必须实现某个类型。

实例 1:

定义一个函数,参数接收什么,返回值就返回什么,并且要求传入的参数都具有 length 属性。

// 直接给参数定义 {length: number} 类型,但是返回值的类型也全都变成了 {length: number},参数原本的类型被丢失
function getInfo1(info: {length: number}) {
  return info
}

let info1 = getInfo1('Lee')
let info2 = getInfo1([1, 3, 3])
let info3 = getInfo1({length: 1})

《六》TypeScript 中的泛型_第5张图片

// 通过泛型约束来实现:Type 就相当于是一个变量,记录了本次调用参数的类型。所以在函数的整个执行过程中,都能一直保留着参数的类型
function getInfo2(info: Type): Type {
  return info
}

let info4 = getInfo2('Lee')
let info5 = getInfo2([1, 3, 3])
let info6 = getInfo2({length: 1})

《六》TypeScript 中的泛型_第6张图片

实例 2:

定义一个函数,接收两个参数,要求第二个参数必须是第一个参数的属性。

// keyof O 其实就相当于是获取 O 的所有 key 的联合类型,'name' | 'age'
function getProperty(obj: O, key: K) {
  return obj[key]
}

const person = {
  name: 'Lee',
  age: 18
}
let info1 = getProperty(person, 'address') // 报错
let info2 = getProperty(person, 'name') // 正确

你可能感兴趣的:(TypeScript,TypeScript)