likes
comments
collection

🤪🤪TS高级用法(一)

作者站长头像
站长
· 阅读数 15

如今,越来越多的项目使用了TypeScript进行编写,我们都知道TypeScriptJavaScript的超集,它为JavaScript提供了强大的类型和语法增强功能,能在项目开发的过程中大大减少错误的产生。而TypeScript也内置了很多的工具类型,接下来,我将带着大家学习TypeScript中的工具类型。

本文中为系列文章的第一篇

Partial

Partial用于将一个类型中的所有属性转变为可选属性。

栗子

interface PhoneType {
  width: number;
  height:  number;
}

const D1:PhoneType={
    width:100,
    height:100
}

// 错误, 缺少height属性
const D2:PhoneType={
    width:100,
}

// 此时,weight和height变为可选属性
// type Partial<T> = { [P in keyof T]?: T[P]; }
const D3:Partial<PhoneType>={
    width:100,
}

分析

可以看到,Partial会将我们传入的类型先通过keyof获取对应的属性名称,在进行遍历,将对应属性类型赋值给P,使用可选的符号?,让属性成为可选属性。

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

Required

Required,从名称上我们就可以猜测到,它是一个将一个类型中所有属性转变为必选属性的方法。

栗子

interface PersonType {
  name: string;
  age?: number;
}

// 正常情况下,age属性可不填写
const p1: PersonType = {
  name: "_island",
};

// 错误,缺少age属性
// 类型 "{ name: string; }" 中缺少属性 "age",但类型 "Required<PersonType>" 中需要该属性。ts(2741)
const p2: Required<PersonType> = {
  name: "zhangsan",
};

// type Required<T> = { [P in keyof T]-?: T[P]; }
// 将age属性变成必选属性
const p3: Required<PersonType> = {
  name: "lisi",
  age: 18,
};

分析

同上面的Partial一样,先通过keyof获取类型中的属性名称,进行遍历操作。这里不同的是在?前面多出了-,意思是将可选属性的?符号去掉,变为必选属性

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

Pick

Pick用于从一个类型中,提取一个或者多个属性出来。

栗子

interface HousesItemType {
  desc: string;
  houseCode: string;
  houseImg: string | string[];
  price: number | string;
  tags: string[];
  title: string;
}

// type Pick<T, K extends keyof T> = { [P in K]: T[P]; }
// 从 HousesItemType 类型中提取出 houseCode houseImg price
type MiniHousesItemType = Pick<
  HousesItemType,
  "houseCode" | "houseImg" | "price"
>;

const item: MiniHousesItemType = {
  houseCode: "39cadd9a",
  houseImg: "file_path",
  price: "1000",
};

分析

这个就很简单了,Pick接受两个参数,从第一个参数类型中抽取第二个参数中类型属性。

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

Readonly

Readonly用于将一个类型中的属性转换为可读属性,也即是后续不能修改这些属性值。

栗子

interface ResultType<T=any>{
    data:T
    status:number
}

const res:ResultType<string>={
    data:'ok',
    status:200
}
res.data='ook!'
// res --> ook!

const res2:Readonly<ResultType<string>>={
    data:'ok',
    status:200
}
// 无法赋值,data是只读属性
// type Readonly<T> = { readonly [P in keyof T]: T[P]; }
res2.data='ook!'

ReadonlyArray

const arr1:Readonly<number[]>=[1,2,3,4,5,6,7,8,9]
// 相当于上面的写法
const arr2:ReadonlyArray<number>=[1,2,3,4,5,6,7,8,9]

分析

Readonly会将我们传入的类型先通过keyof获取对应的属性名称,在进行遍历,将对应属性类型赋值给P,使用Readonly操作符,让其属性转变为可读属性。

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

Record

Record,翻译过来即是记录的意思,用于将一个类型中的属性值映射到另外一个类型。

栗子

interface PersonType {
  name: string;
  age?: number;
}

type Names = "_island" | "zhangsan" | "lisi";

// 将Names作为list的属性名称,PersonType作为属性值类型
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
const list: Record<Names, PersonType> = {
  _island: { age: 10, name: "_island" },
  zhangsan: { age: 5, name: "zhangsan" },
  lisi: { age: 16, name: "lisi" },
};

分析

我们可以看到,将K(K只能是string number symbol类型)转化作为T类型。

type Record<K extends string | number | symbol, T> = { [P in K]: T; }