Built-in Utility Types

Utility TypeDescriptionExample Usage
Partial<T>Makes all fields optional.Partial<User>
Required<T>Makes all fields non-optional.Required<Partial<User>>
Readonly<T>Makes all fields read-only.Readonly<User>
Record<K, T>Creates an object consisting of values corresponding to a specific key set.Record<'a' | 'b', number>
Pick<T, K>Used to select specific fields.Pick<User, 'id' | 'email'>
Omit<T, K>Used to exclude specific fields.Omit<User, 'password'>
Exclude<T, U>Excludes specific types from a union.Exclude<'a' | 'b', 'b'>'a'
Extract<T, U>Preserves only the specified types, discarding the rest.Extract<'a' | 'b', 'b' | 'c'>'b'
NonNullable<T>Excludes null and undefined values.NonNullable<string | null>string
ReturnType<T>Gets the return type of a function.ReturnType<() => number>number
InstanceType<T>Gets the return type of a class (constructor).InstanceType<typeof MyClass>
Parameters<T>Returns the parameter types of a function as a tuple.Parameters<(a: string, b: number) => void>
ConstructorParameters<T>Returns the parameter types of a class's constructor.ConstructorParameters<typeof MyClass>
ThisParameterType<T>Gives the type of the this parameter in a function.ThisParameterType<(this: User, arg: number) => void>
OmitThisParameter<T>Removes the this parameter.OmitThisParameter<(this: User) => void>
ThisType<T>Used to specify the this type in object literals.Advanced use (common in mixins)
Awaited<T>Returns the value a Promise resolves to (TypeScript 4.5+).Awaited<Promise<string>>string

🧪 Custom Utility Types (Commonly used custom combinations)

Although these types are not built into TypeScript, you often need to implement them yourself in projects. This section provides detailed implementations and usage examples for each.

DeepPartial<T>

Makes all properties in an object type recursively optional.
type DeepPartial<T> = T extends object
	? {
			[P in keyof T]?: DeepPartial<T[P]>
		}
	: T
 
// Example usage:
interface NestedUser {
	id: number
	name: string
	address: {
		street: string
		city: string
		zip: number
	}
	preferences: {
		theme: {
			dark: boolean
			fontSize: number
		}
	}
}
 
// With standard Partial:
const partialUser: Partial<NestedUser> = {
	name: 'John',
	// address is still an object with required fields if provided
}
 
// With DeepPartial:
const deepPartialUser: DeepPartial<NestedUser> = {
	name: 'John',
	address: {
		// No need to provide all fields
		street: 'Main St',
	},
	preferences: {
		theme: {
			// Only specifying dark theme
			dark: true,
		},
	},
}

DeepReadonly<T>

Makes all properties in an object recursively read-only, including nested objects.
type DeepReadonly<T> = T extends (infer R)[]
	? ReadonlyArray<DeepReadonly<R>>
	: T extends Function
		? T
		: T extends object
			? {
					readonly [P in keyof T]: DeepReadonly<T[P]>
				}
			: T
 
// Example:
interface Config {
	apiKey: string
	settings: {
		timeout: number
		retries: number
		advanced: {
			logging: boolean
		}
	}
}
 
const config: DeepReadonly<Config> = {
	apiKey: 'abc123',
	settings: {
		timeout: 3000,
		retries: 3,
		advanced: {
			logging: true,
		},
	},
}
 
// This will cause TypeScript errors:
// config.apiKey = "xyz"; // Error: Cannot assign to 'apiKey' because it is a read-only property
// config.settings.timeout = 5000; // Error: Cannot assign to 'timeout' because it is a read-only property
// config.settings.advanced.logging = false; // Error: Cannot assign to 'logging' because it is a read-only property

Mutable<T>

Removes readonly modifiers from all properties in a type.
type Mutable<T> = {
	-readonly [P in keyof T]: T[P]
}
 
// Example:
interface ReadonlyUser {
	readonly id: number
	readonly name: string
}
 
const user: Mutable<ReadonlyUser> = {
	id: 1,
	name: 'John',
}
 
// Now we can modify the properties
user.id = 2 // This works
user.name = 'Jane' // This works

Nullable<T>

Creates a union type of T or null.
type Nullable<T> = T | null
 
// Example:
function fetchData(): Nullable<string> {
	// May return null if data not available
	return Math.random() > 0.5 ? 'Some data' : null
}
 
const data = fetchData()
// Need to check before using
if (data !== null) {
	console.log(data.toUpperCase())
}

OptionalKeys<T>

Returns a union of keys that are optional in the given type.
type OptionalKeys<T> = {
	[K in keyof T]-?: {} extends Pick<T, K> ? K : never
}[keyof T]
 
// Example:
interface User {
	id: number
	name: string
	email?: string
	avatar?: string
}
 
// Results in: "email" | "avatar"
type UserOptionalKeys = OptionalKeys<User>
 
// Usage example:
function hasOptionalField<T>(obj: T, key: OptionalKeys<T>): boolean {
	return key in obj
}
 
const user: User = { id: 1, name: 'John' }
console.log(hasOptionalField(user, 'email')) // false
console.log(hasOptionalField(user, 'avatar')) // false
// console.log(hasOptionalField(user, "id")); // Error: 'id' is not assignable to parameter of type 'email' | 'avatar'

RequiredKeys<T>

Returns a union of keys that are required in the given type.
type RequiredKeys<T> = {
	[K in keyof T]-?: {} extends Pick<T, K> ? never : K
}[keyof T]
 
// Example:
interface User {
	id: number
	name: string
	email?: string
	avatar?: string
}
 
// Results in: "id" | "name"
type UserRequiredKeys = RequiredKeys<User>
 
// Usage example:
function assertRequiredFields<T>(obj: T): void {
	const required: RequiredKeys<T>[] = [] as any
	for (const key of required) {
		if (!(key in obj)) {
			throw new Error(`Missing required field: ${String(key)}`)
		}
	}
}

UnionToIntersection<T>

Converts a union type to an intersection type.
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
	k: infer I
) => void
	? I
	: never
 
// Example:
type Union = { a: string } | { b: number } | { c: boolean }
 
// Results in: { a: string } & { b: number } & { c: boolean }
type Intersection = UnionToIntersection<Union>
 
// Usage example with function overloads:
type Overloads =
	| ((a: string) => number)
	| ((a: number) => string)
	| ((a: boolean) => void)
 
// Results in intersection of all function overloads
type CombinedOverload = UnionToIntersection<Overloads>
// Same as: ((a: string) => number) & ((a: number) => string) & ((a: boolean) => void)

DeepNonNullable<T>

Makes all properties recursively non-nullable.
type DeepNonNullable<T> = T extends object
	? { [P in keyof T]: DeepNonNullable<T[P]> }
	: NonNullable<T>
 
// Example:
interface UserProfile {
	id: number
	name: string | null
	address: {
		street: string | null
		city: string | null
	} | null
}
 
// All null values must be replaced
const profile: DeepNonNullable<UserProfile> = {
	id: 1,
	name: 'John', // Cannot be null
	address: {
		street: 'Main St', // Cannot be null
		city: 'New York', // Cannot be null
	}, // Cannot be null
}

🔮 Summary Table

CategoryUtility Types
Field TransformationPartial, Required, Readonly, Mutable, DeepPartial, DeepReadonly
Field Selection/RemovalPick, Omit, Exclude, Extract, NonNullable
Function & Class TypesReturnType, Parameters, InstanceType, ConstructorParameters, Awaited
This RelatedThisParameterType, OmitThisParameter, ThisType
Record/MappingRecord, UnionToIntersection

If you want, I can explain one of these utility types in more detail with examples, or we can create a custom utility type suitable for your project. 💡

Command Palette

Search for a command to run...