TypeScript provides built-in utility types that transform existing types.

Partial

Makes all properties optional.

interface User {
  name: string;
  age: number;
  email: string;
}

type PartialUser = Partial<User>;
// { name?: string; age?: number; email?: string; }

function updateUser(user: User, updates: Partial<User>): User {
  return { ...user, ...updates };
}

Required

Makes all properties required.

interface Config {
  apiUrl?: string;
  timeout?: number;
}

type RequiredConfig = Required<Config>;
// { apiUrl: string; timeout: number; }

Readonly

Makes all properties readonly.

interface Point {
  x: number;
  y: number;
}

type ReadonlyPoint = Readonly<Point>;
// { readonly x: number; readonly y: number; }

const point: ReadonlyPoint = { x: 10, y: 20 };
// point.x = 30; // ❌ Error

Pick

Select specific properties from a type.

interface User {
  id: number;
  name: string;
  email: string;
  age: number;
}

type UserPreview = Pick<User, "name" | "email">;
// { name: string; email: string; }

Omit

Remove specific properties from a type.

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
}

type PublicUser = Omit<User, "password">;
// { id: number; name: string; email: string; }

Record

Create an object type with specific keys and values.

type UserRoles = Record<string, boolean>;
// { [key: string]: boolean; }

const roles: UserRoles = {
  admin: true,
  user: false,
  guest: false
};

// With specific keys
type Status = "pending" | "approved" | "rejected";
type StatusMap = Record<Status, number>;
// { pending: number; approved: number; rejected: number; }

Exclude

Exclude types from a union.

type T0 = Exclude<"a" | "b" | "c", "a">;
// "b" | "c"

type T1 = Exclude<string | number | (() => void), Function>;
// string | number

Extract

Extract types from a union.

type T0 = Extract<"a" | "b" | "c", "a" | "f">;
// "a"

type T1 = Extract<string | number | (() => void), Function>;
// () => void

NonNullable

Remove null and undefined from a type.

type T0 = NonNullable<string | number | undefined>;
// string | number

type T1 = NonNullable<string[] | null | undefined>;
// string[]

ReturnType

Get the return type of a function.

function getUser() {
  return { name: "Alice", age: 25 };
}

type User = ReturnType<typeof getUser>;
// { name: string; age: number; }

Parameters

Get the parameters of a function as a tuple.

function createUser(name: string, age: number, email: string) {
  // ...
}

type CreateUserParams = Parameters<typeof createUser>;
// [string, number, string]

InstanceType

Get the instance type of a constructor.

class User {
  constructor(public name: string) {}
}

type UserInstance = InstanceType<typeof User>;
// User

Awaited

Get the type that a Promise resolves to (TypeScript 4.5+).

async function getUser() {
  return { name: "Alice", age: 25 };
}

type User = Awaited<ReturnType<typeof getUser>>;
// { name: string; age: number; }

Combining Utility Types

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
}

// Create a type for user updates (all optional, no password, no id, no createdAt)
type UserUpdate = Partial<Omit<User, "id" | "password" | "createdAt">>;
// { name?: string; email?: string; }

// Create a public user view (no password)
type PublicUser = Omit<User, "password">;
// { id: number; name: string; email: string; createdAt: Date; }

Exercises

Exercise 1: Partial and Required

// Create an interface 'Product' with required properties
// Create a type for product updates using Partial
// Create a type for complete product using Required

Exercise 2: Pick and Omit

// Create an interface 'User' with many properties
// Use Pick to create a 'UserSummary' with only name and email
// Use Omit to create a 'PublicUser' without sensitive data

Exercise 3: Record

// Create a Record type for a translation dictionary
// Keys: "en" | "fr" | "es"
// Values: { hello: string; goodbye: string }

Exercise 4: Exclude and Extract

// Create a union type of HTTP methods
// Use Exclude to remove unsafe methods
// Use Extract to get only safe methods

Exercise 5: Combining Utilities

// Create a complex type transformation:
// - Start with a User interface
// - Make all properties optional
// - Remove 'id' and 'createdAt'
// - Make 'email' required again

Best Practices

  1. Use Partial for updates - When you want to update some properties
  2. Use Pick/Omit for views - When you need a subset of properties
  3. Use Record for dictionaries - When you have key-value mappings
  4. Combine utilities - Chain them for complex transformations
  5. Document complex types - Add comments explaining the transformation

Common Mistakes

  1. Using Partial when you need specific properties
// ❌ Too permissive
type Update = Partial<User>;

// ✅ Better - only allow specific fields
type Update = Partial<Pick<User, "name" | "email">>;
  1. Not understanding Exclude/Extract
// Exclude removes from union
type T = Exclude<"a" | "b" | "c", "a">; // "b" | "c"

// Extract keeps from union
type T = Extract<"a" | "b" | "c", "a" | "x">; // "a"
  1. Forgetting ReturnType needs typeof
// ❌ Wrong
type T = ReturnType<getUser>;

// ✅ Correct
type T = ReturnType<typeof getUser>;

Next Steps

Learn about Advanced Types.