神奇的TypeScript -- 进阶篇之实用工具类型

系列文章目录

神奇的TypeScript – 基础篇



前言

TypeScript作为一个强类型语言,TypeScript 为我们也提供了很多实用工具类型,让我们可以以一种方便的方式来操作现有类型并从中创建新类型。他们可以帮助我们更轻松地描述常见类型转换,提高代码的可读性和可维护性。

一、运算符和分布式联合类型

我们先来了解一下基础的几个运算符,这几个运算符我们在后面会经常用到:

keyof: 获取类型中的所有属性名称key,返回一个包含所有属性名称的联合类型。
typeof: 获取类型。
in:遍历,可以用来遍历联合类型。
extends:
1. 用来声明类继承,A extends B也就是A继承B;
2. 定义条件类型,C extends D ? C : nerve即遍历C(联合类型)与D进行比较,如果相同则保留,返回一个不包含D类型的的C类型
infer: infer 只能在条件类型的 extends 子句中使用,用来提取类型信息,并且声明的类型变量只能在条件类型的真值分支中使用。

以及一个特殊的类型判断:
分布式联合类型:当条件类型遇到联合类型时,它会把条件类型应用于联合类型中的每个成员,然后将结果合并成一个新的联合类型。

type DAD<T> = T extends () => infer U ? U : never;

二、实用工具类型

我们先定义一个Person的接口类型

interface Person {
    name: string;
    age: number;
    height?: number;
    what?: null;
    why: undefined;
    sayHello(): void;
}

1. 修改已有的类型属性:Partial|Required|Readonly

Partial 将所有属性改为可选属性。
Required 将所有属性改为必填属性。
Readonly 将所有属性改为只读属性。

1.1 用法

Partial<Type>
Required<Type>
Readonly<Type>

Type:想要修改的类型

1.2 代码示例

// 将所有属性变为可选
type PersonPartial = Partial<Person>;
// 将所有属性变为必选
type PersonRequired = Required<Person>;
// 将所有属性变为只读
type PersonReadonly = Readonly<Person>;

const o: PersonPartial = {}
const p: PersonRequired = {
    name: "",
    sayHello: function (): void {
        throw new Error("Function not implemented.");
    },
    age: 0,
    height: 0,
    what: null,
    why: undefined
};
const q: PersonReadonly = {
    name: "",
    sayHello: function (): void {
        throw new Error("Function not implemented.");
    },
    age: 0,
    why: undefined
};

1.3 手动实现一个Partial

// 实现一个Partial
type PersonPartialCopy<T> = {
    [k in keyof T]: T[k];
}

const PPC: PersonPartialCopy<Person> = {
    name: "",
    sayHello: function (): void {
        throw new Error("Function not implemented.");
    },
    age: 0,
    why: undefined
}

2. 选择或剔除类型中的属性:Pick|Omit

Pick 用于从类型中选取指定的属性。
Omit 用于从类型中排除指定的属性。

2.1 Pick

选择类型中的属性

2.1.1 用法
Pick<Type, Keys>

Type: 要选取属性的类型。
Keys: 要选取的属性的键的联合类型。

type PersonPick = Pick<Person, "name" | "age">;
2.1.2 手动实现一个Pick
type PersonPickRealize<T, K extends keyof T> = {
    [k in K]: T[k];
}
const PPR: PersonPickRealize<Person, "name" | "age"> = {
    name: "",
    age: 0
}

2.2 Omit

剔除类型中的属性

2.2.1 用法
Omit<Type, Keys>

Type: 要排除属性的类型。
Keys: 要排除的属性的键的联合类型。

type PersonOmit = Omit<Person, "name">;
2.2.2 手动实现一个 Omit
type PersonOmitRealize<T, K extends keyof T> = {
    [k in Exclude<keyof T, K>]: T[k]
}
const POR: PersonOmitRealize<Person, "name"> = {
    age: 0,
    sayHello: () => { },
    height: undefined,
    what: undefined,
    why: undefined
}

3. Record

Record用来构造一个所有属性都相同类型的类型

3.1 用法

type PersonRecord = Record<"name" | "age", string>;

3.2 手动实现一个 Record

type PersonRecordRealize<K extends keyof any, T> = {
    [k in K]: T;
}
let s: Symbol = Symbol(1);
const PRR: PersonRecordRealize<"name" | 123, string> = {
    name: "",
    123: ""
}

4. Extract | Exclude

选择联合类型类型中的类型

4.1 Extract

4.1.1 用法
type PersonExtract = Extract<Person | string, Person>;
4.1.2 手动实现
const PEE: PersonExtract = {
    name: "",
    sayHello: () => { },
    age: 0,
    why: undefined
}

4.2 Exclude

剔除联合类型中的一些类型

4.2.1 用法
type PersonExclude = Exclude<Person | string, Person>;
4.2.2 手动实现
type PersonExcludeRealize<T, U> = T extends U ? never : T;
const PE: PersonExclude = "123";

5. ReturnType | Parameters

function foo(a: number, b: string): boolean { return false; }

5.1 ReturnType

获取函数函数返回类型

5.1.1 用法
type FooReturnType = ReturnType<typeof foo>;
5.1.2 手动实现
type ReturnTypeRealize<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : never;

5.2 Parameters

获取函数参数类型,返回一个元组

5.2.1 用法
type FooParameters = Parameters<typeof foo>;
5.2.2 手动实现
type FooParametersRealize<T extends (...args: any) => any> = T extends (...args: infer U) => any ? U : never;
class Animal {
    name: string;
    age: number;

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    sayHello() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

6. InstanceType | ConstructorParameters

6.1 InstanceType

构造函数类型的实例类型

6.1.1 用法

type AnimalInstanceType = InstanceType<typeof Animal>;

6.1.2 手动实现

type AnimalInstanceTypeRealize<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
const AI: AnimalInstanceTypeRealize<typeof Animal> = new Animal("", 0);

6.2 ConstructorParameters

构造函数的类型来构造元组或数组类型

6.2.1 用法
type AnimalConstructorParameters = ConstructorParameters<typeof Animal>;

7. NonNullable

去除联合类型中的null和undefined

7.1 用法

type PersonNonNullable = NonNullable<undefined | null | string>;
const PNN: PersonNonNullable = "123";

7.2 手动实现

type PersonNonNullableRealize<T> = T extends null | undefined ? never : T;
const ONNR: PersonNonNullableRealize<undefined | null | string> = "123";

总结

TypeScript 的实用工具类型是预定义的类型函数,提供对现有类型的便捷转换和操作。可以轻松地创建新类型或修改现有类型,而无需手动编写冗长的类型定义。∂∂∂

  • 提高代码可读性: 提供简洁的语法来表达常见的类型转换,使代码更易于阅读和理解。
  • 增强类型安全性: 通过提供类型检查来帮助您避免常见的类型错误,从而提高代码的可靠性。
  • 简化类型定义: 可以减少需要编写的类型定义代码量,从而提高开发效率。

总而言之,TypeScript 的实用工具类型是编写类型安全、清晰且表达能力强的代码的有力工具。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小前端--可笑可笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值