Bootstrap

TS 关于泛类约束Partial<T>、Required<T>、Readonly<T>

Partial<T>:快速把某个接口类型中定义的属性变成可选

Partial 是 TS 中的一个工具类型(Utility Type),它的作用只有一个:将一个对象类型中的所有属性变为可选属性。换句话说,Partial<T> 接受一个泛型参数 T,并返回一个新的类型,新类型与 T 相同,但是 T 类型中的所有属性都变为可选属性。

type User = {
  id: number;
  name: string;
  age: number;
}
type UpdatedPerson = Partial<User>;

得到的 UpdatedPerson 类型与下面的类型定义是相同的:

type UpdatedPerson = {
  id?: number;
  name?: string;
  age?: number;
}

参考:TS 关于泛类约束partial<T>_ts partial_moannian的博客-CSDN博客

原来Partial这么神!TS中的对象可选属性解决方案_ts中的partial_滕青山ᅠ的博客-CSDN博客

// Partial 源码分析
/**
 * Make all properties in T optional
 */
type Partial<T> = {
  [P in keyof T]?: T[P];
};

这段源码使用关键字 in 和操作符 keyof 定义了一个映射类型。

  • keyof 是 TS 中的索引类型查询操作符,用于获取一个对象类型的所有属性名称的联合类型。
interface User {
  name: string;
  age: number;
  gender: string;
}

type UnionType = keyof User;

User 是一个对象类型,keyof 会获取 User 对象类型的属性名称联合类型,也就是 "name" | "age" | "gender"。UnionType 的类型与下面的类型定义是等价的:

type UnionType = "name" | "age" | "gender";

要注意的是,keyof 操作符只能用于对象类型。除对象类型外的其他类型,keyof 是无法使用的。例如:

type MyNumber = number;
type MyNumberKey = keyof MyNumber; // 编译错误:Type 'number' has no matching index signature for type 'keyof number'
  • 再来看源码中的 in 关键字,这个关键字的作用是用于映射类型的。在这里 in 表示的是迭代联合类型中的每个属性,而泛型 P 就表示这些属性。

这样,Partial 类型中的成员就与传入的泛型 T 中的成员一致了。属性名称后的 ? 表示可选类型,属性值则是取的泛型 T 中的属性值。由此,便将泛型 T 中的属性转变成了可选属性。

Required<T>:把所有可选属性变成必选属性

interface Person {
    name: string;
    age: number;
    sex?: string;
}
/**
* type PersonOptions = {
*   name: string;
*   age: number;
*   sex: string;
* }
*/
type PersonRequired = Required<Person>;

// 实现原理
type Required<T> = {
    [P in keyof T]-?: T[P] // `-?` 符号是一个操作符,用于将属性变为必需的,即必须存在并且不能为 undefined 或 null。
}

Readonly<T>:把所有属性变成只读属性

// 实现原理
/**
 * Make all properties in T readonly
 */
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

;