Built-in utility types (Partial, Required, etc.)
Built-in Utility Types (Partial, Required, etc.)
TypeScript provides a series of built-in utility types to simplify type manipulation. These utility types are based on generics and conditional types, helping developers handle type transformations and combinations more efficiently. Among them, Partial
, Required
, Readonly
, Pick
, Record
, etc., are the most commonly used.
Partial
The Partial
utility type makes all properties of type T
optional. This is particularly useful when partial updates to an object are needed.
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = Partial<User>;
// Equivalent to:
// {
// id?: number;
// name?: string;
// age?: number;
// }
function updateUser(id: number, changes: Partial<User>) {
// Logic to update user
}
updateUser(1, { name: "John" }); // Only updates the name property
The implementation principle of Partial
is based on mapped types:
type Partial<T> = {
[P in keyof T]?: T[P];
};
Required
Required
is the opposite of Partial
. It makes all properties of type T
mandatory.
interface Props {
a?: number;
b?: string;
}
type RequiredProps = Required<Props>;
// Equivalent to:
// {
// a: number;
// b: string;
// }
const obj1: Props = { a: 5 }; // Correct
const obj2: RequiredProps = { a: 5 }; // Error: Missing property 'b'
The implementation principle of Required
:
type Required<T> = {
[P in keyof T]-?: T[P];
};
Readonly
The Readonly
utility type makes all properties of type T
read-only.
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Learn TypeScript",
};
todo.title = "Learn JavaScript"; // Error: Cannot assign to 'title' because it is a read-only property
The implementation principle of Readonly
:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Pick
The Pick
utility type constructs a new type by selecting a set of properties K
from type T
.
interface User {
id: number;
name: string;
age: number;
email: string;
}
type UserBasicInfo = Pick<User, "id" | "name">;
// Equivalent to:
// {
// id: number;
// name: string;
// }
const userBasic: UserBasicInfo = {
id: 1,
name: "John",
};
The implementation principle of Pick
:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Record
The Record
utility type constructs a type with property keys of type K
and property values of type T
.
type PageInfo = {
title: string;
};
type Page = "home" | "about" | "contact";
const nav: Record<Page, PageInfo> = {
home: { title: "Home" },
about: { title: "About" },
contact: { title: "Contact" },
};
The implementation principle of Record
:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Exclude
The Exclude
utility type excludes from T
those types that are assignable to U
.
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<string | number | (() => void), Function>; // string | number
The implementation principle of Exclude
:
type Exclude<T, U> = T extends U ? never : T;
Extract
The Extract
utility type extracts from T
those types that are assignable to U
.
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
The implementation principle of Extract
:
type Extract<T, U> = T extends U ? T : never;
Omit
The Omit
utility type constructs a type by removing property K
from type T
.
interface User {
id: number;
name: string;
age: number;
email: string;
}
type UserWithoutEmail = Omit<User, "email">;
// Equivalent to:
// {
// id: number;
// name: string;
// age: number;
// }
The implementation principle of Omit
:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
NonNullable
The NonNullable
utility type excludes null
and undefined
from type T
.
type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
The implementation principle of NonNullable
:
type NonNullable<T> = T extends null | undefined ? never : T;
Parameters
The Parameters
utility type constructs a tuple type from the parameter types of function type 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 }]
The implementation principle of Parameters
:
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
ReturnType
The ReturnType
utility type obtains the return type of function type 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 }
The implementation principle of ReturnType
:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
InstanceType
The InstanceType
utility type obtains the instance type of a constructor function type.
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>; // Error
The implementation principle of InstanceType
:
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
ThisParameterType
The ThisParameterType
utility type extracts the type of the this
parameter of a function type.
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
The implementation principle of ThisParameterType
:
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
OmitThisParameter
The OmitThisParameter
utility type removes the this
parameter from a function type.
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
The implementation principle of OmitThisParameter
:
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;
ConstructorParameters
The ConstructorParameters
utility type extracts the parameter types of a constructor function type.
type T0 = ConstructorParameters<ErrorConstructor>; // [message?: string]
type T1 = ConstructorParameters<FunctionConstructor>; // string[]
type T2 = ConstructorParameters<RegExpConstructor>; // [pattern: string | RegExp, flags?: string]
The implementation principle of ConstructorParameters
:
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
Advanced Combination Usage
These utility types can be combined to create more complex type manipulations.
interface User {
id: number;
name: string;
age: number;
email: string;
address?: {
street: string;
city: string;
};
}
// Create a read-only, partially updatable user type
type ReadonlyPartialUser = Readonly<Partial<User>>;
// Create a type with only certain fields and mandatory
type RequiredUserFields = Required<Pick<User, "id" | "name">>;
// Create a type excluding certain fields
type UserWithoutPrivateInfo = Omit<User, "email" | "address">;
// Create a deep Partial type
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
type DeepPartialUser = DeepPartial<User>;
// Equivalent to:
// {
// id?: number;
// name?: string;
// age?: number;
// email?: string;
// address?: {
// street?: string;
// city?: string;
// };
// }
Custom Utility Types
In addition to built-in utility types, developers can create their own.
// Create a Nullable type
type Nullable<T> = T | null;
// Create a Promise return type
type PromiseReturnType<T> = T extends Promise<infer R> ? R : T;
// Create an array element type
type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
// Create a function parameter type
type FunctionParams<T> = T extends (...args: infer P) => any ? P : never;
// Create a type that merges two types
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