TypeScript Utility Types
TypeScript provides a set of built-in utility types that help you transform and manipulate existing types. These utilities are essential for creating flexible and reusable type definitions.
Built-in Utility Types
Partial
Makes all properties of T optional.
interface User {
id: number;
name: string;
email: string;
age: number;
}
type PartialUser = Partial<User>;
// Equivalent to:
// {
// id?: number;
// name?: string;
// email?: string;
// age?: number;
// }
// Usage
function updateUser(id: number, updates: Partial<User>) {
return { id, ...updates };
}
updateUser(1, { name: 'John' }); // OK
updateUser(1, { name: 'John', age: 30 }); // OK
Required
Makes all properties of T required.
interface Config {
apiUrl?: string;
timeout?: number;
retries?: number;
}
type RequiredConfig = Required<Config>;
function createClient(config: RequiredConfig) {
return {
url: config.apiUrl,
timeout: config.timeout,
retries: config.retries
};
}
Readonly
Makes all properties of T readonly.
interface MutableUser {
id: number;
name: string;
email: string;
}
type ReadonlyUser = Readonly<MutableUser>;
const user: ReadonlyUser = { id: 1, name: 'John', email: 'john@example.com' };
// user.name = 'Jane'; // Error: Cannot assign to 'name' because it is a read-only property
Pick<T, K>
Selects specific properties from T.
interface User {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
updatedAt: Date;
}
type UserPublicInfo = Pick<User, 'id' | 'name' | 'email'>;
function getUserPublicInfo(user: User): UserPublicInfo {
return {
id: user.id,
name: user.name,
email: user.email
};
}
Omit<T, K>
Excludes specific properties from T.
type UserWithoutPassword = Omit<User, 'password'>;
function createUser(userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>) {
return {
...userData,
id: Math.random(),
createdAt: new Date(),
updatedAt: new Date()
};
}
Record<K, V>
Creates an object type with keys of type K and values of type V.
type Status = 'pending' | 'approved' | 'rejected';
type StatusMessages = Record<Status, string>;
const messages: StatusMessages = {
pending: 'Your request is being processed',
approved: 'Your request has been approved',
rejected: 'Your request has been rejected'
};
Exclude<T, U>
Excludes types from T that are assignable to U.
type AllColors = 'red' | 'green' | 'blue' | 'yellow' | 'purple';
type PrimaryColors = 'red' | 'green' | 'blue';
type SecondaryColors = Exclude<AllColors, PrimaryColors>; // 'yellow' | 'purple'
Extract<T, U>
Extracts types from T that are assignable to U.
type WarmColors = 'red' | 'yellow' | 'orange';
type AvailableWarmColors = Extract<AllColors, WarmColors>; // 'red' | 'yellow'
NonNullable
Excludes null and undefined from T.
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>; // string
Parameters
Extracts the parameter types of a function type T.
function createUser(name: string, age: number, email: string) {
return { name, age, email };
}
type CreateUserParams = Parameters<typeof createUser>; // [string, number, string]
ReturnType
Extracts the return type of a function type T.
function getUser() {
return { id: 1, name: 'John', email: 'john@example.com' };
}
type User = ReturnType<typeof getUser>;
Advanced Utility Types
Custom Utility Types
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
Conditional Utility Types
type Awaited<T> = T extends Promise<infer U> ? U : T;
type IsFunction<T> = T extends (...args: any[]) => any ? true : false;
type FirstParameter<T> = T extends (first: infer P, ...args: any[]) => any ? P : never;
Key Concepts
- Type Transformation: Utility types transform existing types
- Composability: Utility types can be combined and nested
- Generic Constraints: Using
extendsto constrain type parameters - Conditional Types: Using
extendsandinferfor type logic - Template Literal Types: For string manipulation (TypeScript 4.1+)
Common Interview Questions
- What's the difference between
PickandOmit? - How would you create a deep partial type?
- What's the purpose of
Record<K, V>? - How do you extract function parameter types?
- What's the difference between
ExcludeandExtract?
Related Topics
- Type vs Interface
- Generics
- Conditional Types
- Template Literal Types
- Mapped Types