TypeScript provides several built-in utility types that help transform and manipulate types. These are implemented using advanced type features like mapped types and conditional types.
Makes all properties in T optional.
interface User {
id: string
name: string
email: string
age: number
}
type PartialUser = Partial<User>
// {
// id?: string
// name?: string
// email?: string
// age?: number
// }
// Useful for update operations
function updateUser(id: string, updates: Partial<User>) {
// Only update provided fields
}
updateUser('123', { name: 'Alice' }) // OK
updateUser('123', { name: 'Alice', age: 30 }) // OK
Makes all properties in T required (removes optionality).
interface Config {
host?: string
port?: number
timeout?: number
}
type RequiredConfig = Required<Config>
// {
// host: string
// port: number
// timeout: number
// }
function initServer(config: RequiredConfig) {
// All properties are guaranteed to exist
console.log(config.host, config.port, config.timeout)
}
Makes all properties in T readonly.
interface MutablePoint {
x: number
y: number
}
type ImmutablePoint = Readonly<MutablePoint>
// {
// readonly x: number
// readonly y: number
// }
const point: ImmutablePoint = { x: 0, y: 0 }
// point.x = 10 // Error: Cannot assign to 'x' because it is a read-only property
Removes readonly modifiers (not built-in, but useful pattern).
type Mutable<T> = {
-readonly [K in keyof T]: T[K]
}
interface ReadonlyPerson {
readonly name: string
readonly age: number
}
type MutablePerson = Mutable<ReadonlyPerson>
// {
// name: string
// age: number
// }
Creates a type by picking specific properties from T.
interface User {
id: string
name: string
email: string
password: string
createdAt: Date
}
type UserProfile = Pick<User, 'id' | 'name' | 'email'>
// {
// id: string
// name: string
// email: string
// }
// Useful for API responses
function getUserProfile(id: string): UserProfile {
// Return only safe properties
}
Creates a type by omitting specific properties from T.
interface User {
id: string
name: string
email: string
password: string
}
type UserWithoutPassword = Omit<User, 'password'>
// {
// id: string
// name: string
// email: string
// }
// Useful for public user data
function publishUser(user: User): UserWithoutPassword {
const { password, ...publicData } = user
return publicData
}
Excludes types from T that are assignable to U.
type T1 = Exclude<'a' | 'b' | 'c', 'a'> // "b" | "c"
type T2 = Exclude<string | number | boolean, boolean> // string | number
type EventType = 'click' | 'scroll' | 'mousemove' | 'keypress'
type UIEvent = Exclude<EventType, 'scroll'> // "click" | "mousemove" | "keypress"
Extracts types from T that are assignable to U.
type T1 = Extract<'a' | 'b' | 'c', 'a' | 'f'> // "a"
type T2 = Extract<string | number | boolean, boolean> // boolean
type Shape = 'circle' | 'square' | 'triangle' | 'rectangle'
type RoundedShape = Extract<Shape, 'circle'> // "circle"
Excludes null and undefined from T.
type T1 = NonNullable<string | null | undefined> // string
type T2 = NonNullable<string | number | null> // string | number
function processValue(value: string | null | undefined) {
if (value !== null && value !== undefined) {
const nonNull: NonNullable<typeof value> = value
// nonNull is guaranteed to be string
}
}
Constructs an object type with keys of type K and values of type T.
type PageInfo = Record<string, number>
// { [key: string]: number }
const pages: PageInfo = {
home: 1,
about: 2,
contact: 3,
}
// Useful for mapped objects
type UserRole = 'admin' | 'user' | 'guest'
type RolePermissions = Record<UserRole, string[]>
const permissions: RolePermissions = {
admin: ['read', 'write', 'delete'],
user: ['read', 'write'],
guest: ['read'],
}
// With specific keys
type ThemeColors = Record<'primary' | 'secondary' | 'accent', string>
const colors: ThemeColors = {
primary: '#007bff',
secondary: '#6c757d',
accent: '#28a745',
}
Extracts the parameter types of a function type as a tuple.
function createUser(name: string, age: number, email: string) {
// ...
}
type CreateUserParams = Parameters<typeof createUser>
// [name: string, age: number, email: string]
// Useful for higher-order functions
function withLogging<T extends (...args: any[]) => any>(
fn: T,
...args: Parameters<T>
): ReturnType<T> {
console.log('Calling with:', args)
return fn(...args)
}
Extracts the parameter types of a constructor function type.
class User {
constructor(public name: string, public age: number) {}
}
type UserConstructorParams = ConstructorParameters<typeof User>
// [name: string, age: number]
function createUser(...args: UserConstructorParams): User {
return new User(...args)
}
Extracts the return type of a function type.
function createUser() {
return {
id: '123',
name: 'Alice',
email: 'alice@example.com',
}
}
type User = ReturnType<typeof createUser>
// {
// id: string
// name: string
// email: string
// }
// Useful with async functions
async function fetchData() {
return { success: true, data: [1, 2, 3] }
}
type FetchResult = ReturnType<typeof fetchData>
// Promise<{ success: boolean; data: number[] }>
type UnwrappedResult = Awaited<FetchResult>
// { success: boolean; data: number[] }
Extracts the instance type of a constructor function type.
class User {
name: string
constructor(name: string) {
this.name = name
}
}
type UserInstance = InstanceType<typeof User>
// User
function processUser(user: UserInstance) {
console.log(user.name)
}
Extracts the type of the this parameter for a function type.
function toHex(this: Number) {
return this.toString(16)
}
type ThisType = ThisParameterType<typeof toHex> // Number
Removes the this parameter from a function type.
function toHex(this: Number) {
return this.toString(16)
}
type PlainFunction = OmitThisParameter<typeof toHex>
// () => string
Converts string literal type to uppercase.
type Greeting = 'hello'
type LoudGreeting = Uppercase<Greeting> // "HELLO"
// Useful for constants
type HttpMethod = 'get' | 'post' | 'put' | 'delete'
type HttpMethodUppercase = Uppercase<HttpMethod>
// "GET" | "POST" | "PUT" | "DELETE"
Converts string literal type to lowercase.
type Greeting = 'HELLO'
type QuietGreeting = Lowercase<Greeting> // "hello"
Capitalizes the first letter of a string literal type.
type Event = 'click' | 'scroll' | 'mousemove'
type EventHandler = `on${Capitalize<Event>}`
// "onClick" | "onScroll" | "onMousemove"
Uncapitalizes the first letter of a string literal type.
type Greeting = 'Hello'
type LowerGreeting = Uncapitalize<Greeting> // "hello"
Unwraps the type of a Promise (recursively).
type T1 = Awaited<Promise<string>> // string
type T2 = Awaited<Promise<Promise<number>>> // number
type T3 = Awaited<boolean | Promise<string>> // boolean | string
// Useful with async functions
async function fetchUser() {
return { id: '123', name: 'Alice' }
}
type User = Awaited<ReturnType<typeof fetchUser>>
// { id: string; name: string }
Makes all properties and nested properties optional.
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]
}
interface User {
id: string
profile: {
name: string
address: {
street: string
city: string
}
}
}
type PartialUser = DeepPartial<User>
// All properties at all levels are optional
Makes all properties and nested properties readonly.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K]
}
interface User {
id: string
profile: {
name: string
address: {
street: string
city: string
}
}
}
type ImmutableUser = DeepReadonly<User>
// All properties at all levels are readonly
Makes specific properties optional.
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
interface User {
id: string
name: string
email: string
age: number
}
type UserWithOptionalEmail = PartialBy<User, 'email' | 'age'>
// {
// id: string
// name: string
// email?: string
// age?: number
// }
Makes specific properties required.
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>
interface User {
id?: string
name?: string
email?: string
}
type UserWithRequiredId = RequiredBy<User, 'id'>
// {
// id: string
// name?: string
// email?: string
// }
Picks properties by their value type.
type PickByType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K]
}
interface User {
id: string
name: string
age: number
active: boolean
}
type StringProperties = PickByType<User, string>
// { id: string; name: string }
type NumberProperties = PickByType<User, number>
// { age: number }
Omits properties by their value type.
type OmitByType<T, U> = {
[K in keyof T as T[K] extends U ? never : K]: T[K]
}
interface User {
id: string
name: string
age: number
active: boolean
}
type NonStringProperties = OmitByType<User, string>
// { age: number; active: boolean }
Flattens intersections for better IDE tooltips.
type Prettify<T> = {
[K in keyof T]: T[K]
} & {}
type A = { a: string }
type B = { b: number }
type C = A & B
type PrettyC = Prettify<C>
// Displays as: { a: string; b: number }
// Instead of: A & B
Gets the union of all value types.
type ValueOf<T> = T[keyof T]
interface Colors {
red: '#ff0000'
green: '#00ff00'
blue: '#0000ff'
}
type ColorValue = ValueOf<Colors>
// "#ff0000" | "#00ff00" | "#0000ff"
Makes type nullable.
type Nullable<T> = T | null
type NullableString = Nullable<string> // string | null
Makes type nullable or undefined.
type Maybe<T> = T | null | undefined
type MaybeString = Maybe<string> // string | null | undefined
Converts union to intersection (advanced).
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I,
) => void
? I
: never
type Union = { a: string } | { b: number }
type Intersection = UnionToIntersection<Union>
// { a: string } & { b: number }
Utility types can be composed for powerful transformations:
// Make specific properties optional and readonly
type PartialReadonly<T, K extends keyof T> = Readonly<Pick<T, K>> &
Partial<Omit<T, K>>
interface User {
id: string
name: string
email: string
password: string
}
type SafeUser = PartialReadonly<User, 'id' | 'name'>
// {
// readonly id: string
// readonly name: string
// email?: string
// password?: string
// }
// Pick and make readonly
type ReadonlyPick<T, K extends keyof T> = Readonly<Pick<T, K>>
// Omit and make required
type RequiredOmit<T, K extends keyof T> = Required<Omit<T, K>>