TypeScript 使用小技巧

1,107 阅读3分钟

来源:FE研发 - 王尚文

使用映射类型

Partial

T中所有属性变为可选。返回新的接口。

  • 源码:
// Make all properties in T optional
type Partial<T> = {
    [P in keyof T]?: T[P];
};
  • 示例
export interface TModule {
	id: string | number;
	subTitle?: string;
	link: string;
	img: string;
}

// id 、subTitle 、 link 、 img 都可选 
const module: Partial<TModule> = {
	id: "1",
	link: "https://ezbuy.sg/"
}

Requied

T 中所有属性变成必选。返回新接口。

  • 源码实现
// From T, pick a set of properties whose keys are in the union K
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
  • 示例
export interface TModule {
	id: string | number;
	subTitle?: string;
	link: string;
	img: string;
}
// id,subTitle, link, img 都变成必选,缺一不可
const module: Required<TModule> = {
	id: 1,
	subTitle: "",
	link: "",
	img: ""
}

Pick<T, K>

从 T 中取出 一系列 K 的属性。返回 新的接口

  • 源码:
// From T, pick a set of properties whose keys are in the union K
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
  • 示例
export interface TModule {
	id: string | number;
	subTitle?: string;
	link: string;
	img: string;
}
// 从TModule 中选出 id,img, subTittle, 其中 subTitle 可选 
const content: Pick<TModule, "id" | "img" | "subTitle"> = {
	id: "1",
	img: ""
}

Readonly

T中所有属性变为只读。返回新接口。

  • 源码实现
// Make all properties in T readonly
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};
  • 示例
export interface TModule {
	id: string | number;
	subTitle?: string;
	link: string;
	img: string;
}

const content: Readonly<TModule> = {
	id: "1",
	link: "http://ezbuy.sg",
	img: ""
};

content.id = 2; // [ts] Cannot assign to 'id' because it is a read-only property. [2540]

Record<K, T>

遍历K中所有属性,类型都变成T。返回新接口。

  • 源码实现
// Construct a type with a set of properties K of type T
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

  • 示例
export interface TModule {
	id: string | number;
	subTitle?: string;
	link: string;
	img: string;
}
const content: Record< keyof TModule, string> = {
	id: 1, // [ts] 不能将类型“number”分配给类型“string”。 [2322]
	link: "http://ezbuy.sg",
	img: "xx",
	subTitle: "xx" // 注意 subTittle 会变成必选
}

Exclude<T, U>

从T中剔除所有U中存在的属性。 返回新接口描述。相当于求T与U的差集。

  • 源码实现
// Exclude from T those types that are assignable to U
type Exclude<T, U> = T extends U ? never : T

  • 示例
/** 画布最细粒度数据结构 */
export interface TModule {
	/** 模块ID */
	id: string | number;
	/** 模块副标题 */
	subTitle?: string;
	/** 模块 view more 地址  */
	address: string;
	/** 标题左侧 icon */
	img: string;
}

const content: Exclude<keyof TModule, "id" | "img"> = "subTitle"; // 可以为 subtitle 、address, 不能为 id, img

Extract<T, U>

从T中选择U中存在的类型。返回新的接口。相当于求T与U的交集

  • 源码实现
// Extract from T those types that are assignable to U
type Extract<T, U> = T extends U ? T : never;
  • 示例
/** 画布最细粒度数据结构 */
export interface TModule {
	/** 模块ID */
	id: string | number;
	/** 模块副标题 */
	subTitle?: string;
	/** 模块 view more 地址  */
	address: string;
	/** 标题左侧 icon */
	img: string;
}
const content: Extract<keyof TModule, "id" | "img"> = "id"; // 可以为id, img, 不能为 subtitle 、address

Omit<T, U>

忽略T中已经存在于U中的所有属性。相当于求T与U的补集。

  • 源码实现
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
  • 示例
/** 画布最细粒度数据结构 */
export interface TModule {
	/** 模块ID */
	id: string | number;
	/** 模块副标题 */
	subTitle?: string;
	/** 模块 view more 地址  */
	address: string;
	/** 标题左侧 icon */
	img: string;
}

const content: Omit<TModule, "link"|"id"> = {
	img: "https://icon_address",
	address: "",
	// 不能包含 link 和 id
}

注释很重要

可以配合VS code 提示使用。注释格式 /** comment */

图片描述

用联合类型,替代可选属性

如果uidid只可能有一个存在

interface TModule {
	uid?: string;
	id?: string;
}
 // 可以用联合类型来代替
type TModule = { uid: string } | { id: string }