Course

TypeScript Utility Types: Syntax, Usage, and Examples

TypeScript utility types help you transform existing types without rewriting or duplicating code. These built-in tools simplify complex type operations and make your codebase more maintainable. With just a few keywords, you can make properties optional, remove them, pick certain ones, or create completely new type combinations.

How to Use TypeScript Utility Types

You apply TypeScript utility types directly to existing types or interfaces. The syntax usually follows a pattern like this:

tsx
type Modified = UtilityType<OriginalType, Parameters>;

Let’s look at the most useful utility types TypeScript offers.

Common Utility Types in TypeScript

Partial

Makes all properties of a type optional.

tsx
type User = { name: string; age: number; }; type PartialUser = Partial<User>; // Now this is valid: const u: PartialUser = { name: "Alice" };

Use this when you’re only updating part of an object, like in a patch function.

Required

Makes all optional properties required.

tsx
type OptionalUser = { name?: string; age?: number; }; type RequiredUser = Required<OptionalUser>; const u: RequiredUser = { name: "Bob", age: 28 }; // Both fields now required

Readonly

Prevents reassignment of properties after initialization.

tsx
type User = { name: string; age: number; }; const u: Readonly<User> = { name: "Carol", age: 22 }; // u.age = 23; // Error: Cannot assign to 'age'

Use this to protect values from accidental changes.

Pick

Creates a new type by selecting specific properties.

tsx
type User = { id: number; name: string; email: string; }; type BasicUser = Pick<User, "id" | "name">;

Omit

The opposite of Pick. It excludes specified properties.

tsx
type BasicUser = Omit<User, "email">;

Record

Creates a type with a fixed set of property keys and the same value type for all.

tsx
type Scores = Record<string, number>; const gameScores: Scores = { Alice: 90, Bob: 85, };

This is helpful for objects with dynamic keys but consistent values.

Exclude

Removes specific members from a union.

tsx
type Roles = "admin" | "editor" | "guest"; type PublicRoles = Exclude<Roles, "admin">;

Extract

The opposite of Exclude. It keeps only the matching members.

tsx
type EditorRoles = Extract<Roles, "editor" | "guest">;

NonNullable

Removes null and undefined from a type.

tsx
type MaybeString = string | null | undefined; type DefinitelyString = NonNullable<MaybeString>;

ReturnType

Gets the return type of a function.

tsx
function getAge(): number { return 30; } type Age = ReturnType<typeof getAge>; // number

Parameters

Extracts the parameter types of a function into a tuple.

tsx
function greet(name: string, age: number): void {} type GreetArgs = Parameters<typeof greet>; // [string, number]

When to Use Utility Types in TypeScript

Use TypeScript utility types when you:

  • Want to avoid repeating type definitions.
  • Need to create flexible, reusable APIs.
  • Transform existing types in a safe, predictable way.
  • Work with forms, API payloads, or UI states that change over time.
  • Need to handle optional or readonly data structures.

Utility types that TypeScript provides can make your code easier to maintain and reduce room for human error.

Examples of Using Utility Types

Building Form State Types

tsx
type Product = { name: string; price: number; inStock: boolean; }; type ProductFormState = Partial<Product>;

This lets you build a form where fields can be filled in gradually.

Creating Immutable Config Objects

tsx
type Config = { apiUrl: string; timeout: number; }; const appConfig: Readonly<Config> = { apiUrl: "https://api.example.com", timeout: 5000, }; // appConfig.timeout = 3000; // Error: Cannot assign

Modeling API Response with Omit

If your API returns data including fields you don’t want to expose on the frontend:

tsx
type FullUser = { id: number; name: string; password: string; }; type PublicUser = Omit<FullUser, "password">;

You can now safely expose PublicUser in your components.

Learn More About TypeScript Utility Types

Custom Utility Types

You’re not limited to built-in types. You can define your own:

tsx
type Nullable<T> = { [P in keyof T]: T[P] | null };

This allows you to convert all properties of a type into nullable versions.

tsx
type Profile = { name: string; age: number; }; type NullableProfile = Nullable<Profile>;

Deep Utility Types

TypeScript utility types only work on the first level of properties. For deeply nested types, use community tools or write recursive custom types. For example:

tsx
type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; };

This allows you to make even nested properties optional.

Utility Types for Component Props

If you use frameworks like React, you’ll often create types based on props:

tsx
type ButtonProps = { label: string; onClick: () => void; disabled?: boolean; }; type RequiredProps = Required<ButtonProps>;

You can also extract prop types from components with React.ComponentProps<typeof Button>.

Combining Utility Types

You can chain utility types to create exactly what you need:

tsx
type EditableUser = Partial<Omit<User, "id">>;

This makes all fields optional—except the one you left out.

Tips for Using Utility Type TypeScript Tools Effectively

  • Use utility types for fast prototyping and cleaner code.
  • Avoid deeply nested generics if you can simplify the base types.
  • Read the type signature! Knowing what utility types return helps you predict behavior.
  • When working with libraries like Redux or React Query, utility types are great for transforming API responses or state slices.

Best Practices

  • Use Partial for draft forms or patch endpoints.
  • Use Pick and Omit to reuse existing types safely.
  • Use Readonly when passing down props or shared config.
  • Avoid overcomplicating your types—just because you can nest utility types doesn’t mean you should.
  • Combine built-in and custom utility types to stay DRY and type-safe.

The TypeScript utility types built into the language give you superpowers for shaping data models. From building cleaner forms to extracting just the right fields from a backend API, utility types in TypeScript let you focus on logic—not boilerplate.