【TypeScript】 泛型工具(九)

本文详细介绍了TypeScript中的extends关键字在接口继承和条件判断中的应用,以及infer、keyof、typeof、in等其他类型操作符,包括Partial、Required、Readonly、Mutable、Exclude、Extract、Pick、Record、Omit和ReturnType的用法和示例。
摘要由CSDN通过智能技术生成
一、extends

这里主要介绍下 extends 关键字在 TS 中的两种用法,即接口继承和条件判断。

1、接口继承

extends 做继承功能,同 ES6 的 Class 语法用它来做类的继承用法类似。实例代码如下:

interface IName {
  name: string
}
 
interface IAge {
  age: number
}
 
interface IPerson extends IAge, IName {
  sex: string
}
 
const obj: IPerson  = {
  age: 18,
  name: 'Jenny',
  sex: '女'
}

上述代码中,IAge 和 IName 两个接口,分别定义了 age,name属性,IPerson 则使用 extends 多重继承的方法,继承了 IAge 和 IName,同时定义了自身属性 sex,此时 IPerson 除了自身属性外,还同时拥有了来自 IAge 和 IName 的属性。

2、条件判断

条件判断会以一个条件表达式进行类型关系检测,从而在两种类型中选择其一。

T extends U ? X : Y

上述代码含义为:如果 T 包含的类型是 U 包含的类型的 ‘子集’,那么取结果 X,否则取结果 Y。

实现一个简单的示例代码:

type WhatType<T> = T extends null | undefined ? never : T
 
let typeString: WhatType<string> = 'abc' // string 类型
let typeNull: WhatType<null> // never 类型

上述代码含义为:如果泛型参数 T 为 null 或 undefined,那么取 never,否则直接返回 T。

二、infer

在条件类型语句中,可以用 infer 声明一个类型变量,并且对它进行使用。

infer 可以在 extends 的条件语句中推断待推断的类型。示例代码如下:

type ParamType<T> = T extends (...args: infer P) => any ? P : T;
 
interface User {
  name: string;
  age: number;
}
 
type Func = (user: User) => void;
 
type Param = ParamType<Func>; // Param = User
type AA = ParamType<string>; // string
三、keyof - 枚举类型(可以理解为 keyof 对象类型)

keyof 操作符用来获取某种类型的所有 key 值,返回一个联合类型。示例代码如下:

interface IPerson {
  name: string,
  age: number
}
 
type allKey1 = keyof IPerson // 'name' | 'age'
 
type allKey2 = keyof IPerson[] // 'length | 'toString | 'pop' | 'push' | 'concat' | 'join' | ......
 
type allKey3 = keyof { [x: string]: IPerson } // string | number

四、typeof

typeof 操作符用来在类型上下文中获取变量或者属性的类型。示例代码如下:

interface IPerson {
  name: string,
  age: number
}
 
const user: IPerson = {
  name: 'jenny',
  age: 18
}
 
type student = typeof user // IPerson
五、in - 枚举类型

in 操作符用来遍历枚举类型。示例代码如下:

type keys = 'a' | 'b' | 'c'
 
type obj = {
  [p in keys]: any
} // { a: any, b: any, c: any}
六、Partial - 对象类型

Partial 的作用是将某个类型里的属性全部变成可选,该方法是联合了 keyof 和 in 实现的。

type Partial<T> = {
    [P in keyof T]?: T[P]  
}

以上代码中,首先通过 keyof T 拿到 T 的所有属性名,然后使用 in 进行遍历,将值赋给 P,最后通过 T[P] 取得相应的属性值。中间的 ? 号,用于将所有属性变为可选。示例代码如下:

interface IPerson {
  name: string,
  age: number
}
 
type person = Partial<IPerson>
 
// 相当于
// type person = {
//   name?: string | undefined;
//   age?: number | undefined;
// }
七、Required - 对象类型

Required 的作用就是将某个类型中的属性全部变为必选。

type Required<T> = {
    [P in keyof T]-?: T[P];
};

-? 的作用就是把可选属性的可选性去掉,使该属性变成必选项。示例代码如下:

interface IPerson {
  name?: string,
  age?: number
}
 
type person = Required<IPerson>
 
// 相当于
// type person = {
//   name: string;
//   age: number;
// }
八、Readonly - 对象类型

Readonly 的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。

type Readonly<T> = {
    readonly [P in keyof T]: T[P]
}

在每一个 key 前面加上 readonly。示例代码如下:

interface IPerson {
  name: string,
  age: number
}
 
type person = Readonly<IPerson>
 
// 相当于
// type person = {
//   readonly name: string;
//   readonly age: number;
// }
 
const obj:person = {
  name: 'lucy',
  age: 18
}
// 此处 TS 会报错:无法为 name 重新赋值,因为它是只读属性
obj.name="jenny"
九、Mutable - 对象类型

Mutable 的作用是将 T 中所有属性的 readonly 移除。

type Mutable<T> = {
    -readonly [P in keyof T]: T[P]
}

在每一个 key 前面加上 -readonly。示例代码如下:

interface IPerson {
  readonly name: string,
  readonly age: number
}
 
type person = Mutable<IPerson>
 
// 相当于
// type person = {
//   name: string;
//   age: number;
// }
十、Exclude - 枚举类型

Exclude<T, U> 的作用是将某个类型中属于另一个的类型移除掉。

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

实现效果为从 T 中去除 T 与 U 的交集后的类型。示例代码如下:

type exclude0 = Exclude<string | number | boolean, number> // string | boolean
 
type exclude1 = Exclude<'a' | 'b' | 'c', 'a' | 'c'> // 'b'
十一、Extract - 枚举类型

Extract<T, U> 的作用是将某个类型中属于另一个的类型提取出来。

type Extract<T, U> = T extends U ? T : never;

这个和上面的 Exclude 恰好相反,实现效果为从 T 中提取 T 与 U 的交集类型。示例代码如下:

type extract0 = Extract<string | number | boolean, number> // number
 
type extract1 = Extract<'a' | 'b' | 'c', 'a' | 'c'> // 'a' | 'c
十二、Pick - 对象类型

Pick<T, K extends keyof T> 的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子属性。

type Pick<T, K extends keyof T> = {
    [P in K]: T[P]
}

T 是多类型,K 是 T 的部分类型,然后遍历 K 拿到键,再去 T 里拿到相应的值。简单来说就是:

从 T 中提取出 T 与 K 属性值相同的属性。示例代码如下:

interface IPerson {
  name: string,
  age: number,
  sex: string
}
 
type person = Pick<IPerson, 'name'>
 
const user: person = {
  name: 'jenny',
  age: 18 // TS 提示报错,age 不在 person 类型中
}

Pick 与 Extract 都有从 T 中提取 T 与 K 相交的那部分,它们的区别在于 Pick 作用于对象类型,返回的类型用于定义对象;Extract 作用与枚举类型,返回的类型用于定义枚举类型变量。

十三、Record

Record<K extends keyof any, T> 的作用是将 K 中所有的属性的值转换为 T 类型。

type Record<K extends keyof any, T> = {
    [P in K]: T
}

将 K 中有类型的属性进行遍历,再将每个 key 赋值为 T 类型。示例代码如下:

type record0 = Record<'a' | 'b', number>
 
// 相当于
// type record0 = {
//   a: number,
//   b: number
// }
十四、Omit

Omit<T, K extends keyof any> 的作用是使用 T 类型中除了 K 类型的所有属性。

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

实现效果为从对象 T 中剔除 key 为 K 中的属性。

interface IPerson {
  name: string,
  age: number,
  sex: string
}
 
type person = Omit<IPerson, 'name'>
 
// 相当于
// type person = {
//   age: number,
//   sex: string
// }
十五、ReturnType

ReturnType 的作用是用于获取函数 T 的返回类型。

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

示例代码如下:

type T1 = ReturnType<() => string> // string
 
type T2 = ReturnType<(s: string) => void> // void
十六、 NonNullable - 枚举类型

NonNullable 的作用是剔除 T 为 null、undefined 的类型。

type NonNullable<T> = T extends null | undefined ? never : T;

示例代码如下:

type T = NonNullable<string | string[] | null | undefined> // string | string[]

原文链接:https://blog.csdn.net/lhz_333/article/details/124468366

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值