阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 内置工具类型(Partial, Required等)

内置工具类型(Partial, Required等)

作者:陈川 阅读数:42262人阅读 分类: TypeScript

内置工具类型(Partial, Required等)

TypeScript提供了一系列内置工具类型,用于简化类型操作。这些工具类型基于泛型和条件类型,能够帮助开发者更高效地处理类型转换和组合。Partial、Required、Readonly、Pick、Record等是其中最常用的几种。

Partial

Partial工具类型将类型T的所有属性变为可选属性。这在需要部分更新对象时特别有用。

interface User {
  id: number;
  name: string;
  age: number;
}

type PartialUser = Partial<User>;
// 等同于
// {
//   id?: number;
//   name?: string;
//   age?: number;
// }

function updateUser(id: number, changes: Partial<User>) {
  // 更新用户逻辑
}

updateUser(1, { name: "张三" }); // 只更新name属性

Partial的实现原理是基于映射类型:

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

Required

Required与Partial相反,它将类型T的所有属性变为必选属性。

interface Props {
  a?: number;
  b?: string;
}

type RequiredProps = Required<Props>;
// 等同于
// {
//   a: number;
//   b: string;
// }

const obj1: Props = { a: 5 }; // 正确
const obj2: RequiredProps = { a: 5 }; // 错误,缺少属性b

Required的实现原理:

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

Readonly

Readonly工具类型将类型T的所有属性变为只读属性。

interface Todo {
  title: string;
}

const todo: Readonly<Todo> = {
  title: "学习TypeScript",
};

todo.title = "学习JavaScript"; // 错误,无法分配到"title",因为它是只读属性

Readonly的实现原理:

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

Pick

Pick工具类型从类型T中选择一组属性K来构造新类型。

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}

type UserBasicInfo = Pick<User, "id" | "name">;
// 等同于
// {
//   id: number;
//   name: string;
// }

const userBasic: UserBasicInfo = {
  id: 1,
  name: "张三",
};

Pick的实现原理:

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

Record

Record工具类型构造一个类型,其属性键为K,属性值为T。

type PageInfo = {
  title: string;
};

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  home: { title: "首页" },
  about: { title: "关于" },
  contact: { title: "联系" },
};

Record的实现原理:

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

Exclude

Exclude工具类型从类型T中排除那些可以赋值给U的类型。

type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<string | number | (() => void), Function>; // string | number

Exclude的实现原理:

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

Extract

Extract工具类型从类型T中提取那些可以赋值给U的类型。

type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void

Extract的实现原理:

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

Omit

Omit工具类型构造一个类型,它从类型T中删除属性K。

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}

type UserWithoutEmail = Omit<User, "email">;
// 等同于
// {
//   id: number;
//   name: string;
//   age: number;
// }

Omit的实现原理:

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

NonNullable

NonNullable工具类型从类型T中排除null和undefined。

type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]

NonNullable的实现原理:

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

Parameters

Parameters工具类型从函数类型T的参数中构造一个元组类型。

declare function f1(arg: { a: number; b: string }): void;

type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [s: string]
type T2 = Parameters<<T>(arg: T) => T>; // [arg: unknown]
type T3 = Parameters<typeof f1>; // [arg: { a: number; b: string }]

Parameters的实现原理:

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

ReturnType

ReturnType工具类型获取函数类型T的返回类型。

declare function f1(): { a: number; b: string };

type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<<T>() => T>; // unknown
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[]
type T4 = ReturnType<typeof f1>; // { a: number; b: string }

ReturnType的实现原理:

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

InstanceType

InstanceType工具类型获取构造函数类型的实例类型。

class C {
  x = 0;
  y = 0;
}

type T0 = InstanceType<typeof C>; // C
type T1 = InstanceType<any>; // any
type T2 = InstanceType<never>; // never
type T3 = InstanceType<string>; // 错误

InstanceType的实现原理:

type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;

ThisParameterType

ThisParameterType工具类型提取函数类型的this参数类型。

function toHex(this: Number) {
  return this.toString(16);
}

type T0 = ThisParameterType<typeof toHex>; // Number
type T1 = ThisParameterType<(this: Window, name: string) => void>; // Window
type T2 = ThisParameterType<(name: string) => void>; // unknown

ThisParameterType的实现原理:

type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;

OmitThisParameter

OmitThisParameter工具类型从函数类型中移除this参数。

function toHex(this: Number) {
  return this.toString(16);
}

type T0 = OmitThisParameter<typeof toHex>; // () => string
type T1 = OmitThisParameter<(this: Window, name: string) => void>; // (name: string) => void

OmitThisParameter的实现原理:

type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;

ConstructorParameters

ConstructorParameters工具类型从构造函数类型中提取参数类型。

type T0 = ConstructorParameters<ErrorConstructor>; // [message?: string]
type T1 = ConstructorParameters<FunctionConstructor>; // string[]
type T2 = ConstructorParameters<RegExpConstructor>; // [pattern: string | RegExp, flags?: string]

ConstructorParameters的实现原理:

type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;

高级组合使用

这些工具类型可以组合使用,创建更复杂的类型操作。

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
  address?: {
    street: string;
    city: string;
  };
}

// 创建一个只读的、部分更新的用户类型
type ReadonlyPartialUser = Readonly<Partial<User>>;

// 创建一个只包含某些字段且必填的类型
type RequiredUserFields = Required<Pick<User, "id" | "name">>;

// 创建一个排除某些字段的类型
type UserWithoutPrivateInfo = Omit<User, "email" | "address">;

// 创建一个深度Partial类型
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

type DeepPartialUser = DeepPartial<User>;
// 等同于
// {
//   id?: number;
//   name?: string;
//   age?: number;
//   email?: string;
//   address?: {
//     street?: string;
//     city?: string;
//   };
// }

自定义工具类型

除了内置工具类型,开发者也可以创建自己的工具类型。

// 创建一个Nullable类型
type Nullable<T> = T | null;

// 创建一个Promise返回值类型
type PromiseReturnType<T> = T extends Promise<infer R> ? R : T;

// 创建一个数组元素类型
type ArrayElement<ArrayType extends readonly unknown[]> = 
  ArrayType extends readonly (infer ElementType)[] ? ElementType : never;

// 创建一个函数参数类型
type FunctionParams<T> = T extends (...args: infer P) => any ? P : never;

// 创建一个合并两个类型的类型
type Merge<A, B> = {
  [K in keyof A | keyof B]: 
    K extends keyof B ? B[K] :
    K extends keyof A ? A[K] :
    never;
};

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:映射类型基础

下一篇:自定义工具类型

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌