- Abstract class
- Annotations
- Array
- Asserts
- Class
- Const
- Decorators
- Default parameter
- Dictionary
- Enum
- For loop
- forEach()
- Function
- Generics
- Index signature
- Infer
- Inheritance
- Interface
- Let
- Map type
- Mixin
- Module
- Namespace
- Never
- Object type
- Operator
- Optional parameter
- Promise
- Property
- Tuples
- Type alias
- Type guard
- Type narrowing
- Union
- Utility types
- Var
- Void
TYPESCRIPT
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:
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.
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.
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.
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.
type User = {
id: number;
name: string;
email: string;
};
type BasicUser = Pick<User, "id" | "name">;
Omit
The opposite of Pick
. It excludes specified properties.
type BasicUser = Omit<User, "email">;
Record
Creates a type with a fixed set of property keys and the same value type for all.
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.
type Roles = "admin" | "editor" | "guest";
type PublicRoles = Exclude<Roles, "admin">;
Extract
The opposite of Exclude
. It keeps only the matching members.
type EditorRoles = Extract<Roles, "editor" | "guest">;
NonNullable
Removes null
and undefined
from a type.
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>;
ReturnType
Gets the return type of a function.
function getAge(): number {
return 30;
}
type Age = ReturnType<typeof getAge>; // number
Parameters
Extracts the parameter types of a function into a tuple.
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
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
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:
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:
type Nullable<T> = { [P in keyof T]: T[P] | null };
This allows you to convert all properties of a type into nullable versions.
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:
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:
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:
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
andOmit
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.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.