Utility Types
The TypeScript stdlib ships 20+ built-in utility types - Partial, Readonly, Pick, Omit, Exclude, ReturnType, and Awaited cover most day-to-day needs.
TypeScript's standard library ships a set of utility types built from mapped types, conditional types, and infer. You don't need to install anything - they're available in every TypeScript project.
Partial<T> makes every property optional. Required<T> does the reverse. Readonly<T> prevents mutation. Record<K, V> constructs an object type with keys K and values V - useful for lookup tables and index signatures.
type User = { id: string; name: string; email: string };
// Partial - all fields optional (common for update payloads)
type UserPatch = Partial<User>;
// { id?: string; name?: string; email?: string }
// Required - all fields mandatory (strips optional markers)
type FullUser = Required<UserPatch>;
// { id: string; name: string; email: string }
// Readonly - no assignments after construction
type ImmutableUser = Readonly<User>;
const u: ImmutableUser = { id: "1", name: "Ada", email: "ada@example.com" };
// u.name = "Grace"; // Error: cannot assign to 'name' - it is read-only
// Record - maps a union of keys to a value type
type RolePermissions = Record<"admin" | "editor" | "viewer", string[]>;
const permissions: RolePermissions = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
viewer: ["read"],
};Pick<T, K> keeps only the listed keys. Omit<T, K> drops them. Exclude<T, U> removes members of a union that extend U. Extract<T, U> keeps only members that extend U.
type Article = {
id: string;
title: string;
body: string;
authorId: string;
publishedAt: Date | null;
};
// Pick - keep only what the list endpoint needs
type ArticleSummary = Pick<Article, "id" | "title" | "publishedAt">;
// { id: string; title: string; publishedAt: Date | null }
// Omit - strip internal fields before sending to the client
type PublicArticle = Omit<Article, "authorId">;
// { id: string; title: string; body: string; publishedAt: Date | null }
type Status = "pending" | "active" | "suspended" | "deleted";
// Exclude - remove specific members from a union
type LiveStatus = Exclude<Status, "deleted" | "suspended">;
// "pending" | "active"
// Extract - keep only the matching members
type TerminalStatus = Extract<Status, "suspended" | "deleted">;
// "suspended" | "deleted"ReturnType<F> extracts the return type of a function. Parameters<F> extracts the parameter types as a tuple. InstanceType<C> extracts the instance type of a class constructor. Awaited<T> recursively unwraps Promise wrappers.
function fetchUser(id: string): Promise<{ id: string; name: string }> {
return Promise.resolve({ id, name: "Ada" });
}
// ReturnType - derive the return type without repeating it
type FetchUserReturn = ReturnType<typeof fetchUser>;
// Promise<{ id: string; name: string }>
// Awaited - unwrap the Promise
type ResolvedUser = Awaited<FetchUserReturn>;
// { id: string; name: string }
// Parameters - extract argument types as a tuple
type FetchUserParams = Parameters<typeof fetchUser>;
// [id: string]
class Repository {
constructor(private db: string) {}
find(id: string): Promise<{ id: string }> {
return Promise.resolve({ id });
}
}
// InstanceType - get the type of an instance from its constructor
type RepoInstance = InstanceType<typeof Repository>;
// RepositoryIn production
ReturnType<typeof fn> is especially useful for third-party code you can't modify - derive the type from its runtime behavior instead of maintaining a duplicate annotation that will drift. Awaited<T> is essential for async pipelines: Awaited<ReturnType<typeof fetchUser>> gives you the resolved payload type without additional ceremony. For update payloads, reach for Partial<T> at the API boundary and Required<T> at the persistence boundary - this makes the required/optional contract explicit at every layer. Avoid Partial in function bodies where the data should already be complete; a missing field should be a type error, not a runtime surprise.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free