Omit Utility Type in TypeScript
Omit creates a new type by removing specific properties from an existing type. Use it when it is easier to say what to exclude than what to include.
The TypeScript Omit utility type creates a new type by removing specific properties from an existing type. You pass it a type and a union of property names to exclude. The result is everything from the original type except the named fields.
Omit is the complement of Pick utility type in TypeScript. Pick includes only the properties you name, while Omit includes everything except the properties you name.
When you want most of a type's fields and only need to drop a few, Omit is the clearer choice.
interface User {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
}
type SafeUser = Omit<User, "password">;SafeUser has every property from User except password. If you try to add password to a SafeUser object, the compiler rejects it. This pattern is common when sending user data to the client: you want all fields except the sensitive ones, and listing every safe field by hand would be easy to forget as the User interface grows.
How Omit works
Omit takes two type arguments. The first is the source object type. The second is a union of string literal types for the keys to remove:
interface Product {
id: number;
title: string;
price: number;
stock: number;
internalCode: string;
}
type PublicProduct = Omit<Product, "internalCode" | "stock">;Two properties are removed. The result has three fields: id, title, and price.
If Product gains a new property later, PublicProduct automatically includes it, unless you also add that new property to the Omit union. This makes Omit a good choice when your public type should stay close to the internal type, since you only maintain a short exclusion list instead of a long inclusion list.
Omit vs Pick: when to use which
Both Omit and Pick can produce the same type. The difference is in which one reads more naturally for your use case.
| Scenario | Use | Why |
|---|---|---|
| Removing 1 or 2 sensitive fields | Omit | Naming what to remove is clearer |
| Selecting 2 or 3 display fields | Pick | Naming what to keep is clearer |
| Type has many properties, want most | Omit | Avoids listing 20 fields |
| Type has many properties, want few | Pick | Avoids listing 20 exclusions |
The next example shows the same result expressed both ways on a larger interface, so you can compare how each reads. Start with a report type that has both internal and public fields:
interface FullReport {
id: number;
title: string;
body: string;
author: string;
status: string;
createdAt: Date;
updatedAt: Date;
}Omit removes the two internal fields and keeps everything else, while Pick would need to name all five public fields to reach the same result:
type PublicReport = Omit<FullReport, "status" | "updatedAt">;
type PublicReportPick = Pick<FullReport, "id" | "title" | "body" | "author" | "createdAt">;Both lines produce the same type. The Omit version is easier to read and maintain because it says what to remove instead of listing everything to keep. If FullReport gains a new public field, the Omit version includes it automatically, but the Pick version needs to be updated by hand.
Omit for form data types
Forms often exclude server-managed fields, such as an id assigned by the database or timestamps set automatically when a record is created or updated. Omit makes it simple to describe exactly what a form should collect.
interface Task {
id: number;
title: string;
description: string;
dueDate: Date;
completed: boolean;
createdAt: Date;
updatedAt: Date;
}A create-task form should not ask the user for an id, a completion flag, or timestamps, since the server fills those in. Omit removes exactly those fields, and the resulting input type feeds into a function that builds the full Task:
type CreateTaskInput = Omit<Task, "id" | "createdAt" | "updatedAt" | "completed">;
function createTask(input: CreateTaskInput): Task {
return {
...input,
id: Math.random(),
completed: false,
createdAt: new Date(),
updatedAt: new Date(),
};
}The function accepts the fields the user provides and fills in the server-managed fields itself. CreateTaskInput stays in sync with Task automatically. If you add a new field to Task that the user should provide, CreateTaskInput includes it by default, without you having to touch the form type at all.
Omit does not error on missing keys
Unlike Pick, Omit does not complain if you try to remove a key that does not exist on the source type. This is a small but important difference between the two utility types.
interface Widget {
name: string;
price: number;
}
type Result = Omit<Widget, "name" | "color">;The compiler silently ignores "color" because it is not a key of Widget. This can hide typos. If you meant to write "price" but typed "prcie", Omit would ignore the typo and leave price in the type, which is easy to miss during a code review.
Constraining the second type argument to only valid keys catches this kind of mistake at compile time instead:
type StrictOmit<T, K extends keyof T> = Omit<T, K>;
type Safe = StrictOmit<Widget, "prcie">;
// Error: Type '"prcie"' does not satisfy the constraint 'keyof Widget'.The constraint forces K to only be keys that actually exist on T. This is useful in library code or any place where you want stricter checks than the built-in Omit provides.
Combining Omit with other utility types
Omit composes well with other utility types. A common pattern is Omit plus Partial utility type in TypeScript for update payloads, where some fields should never change and the rest are optional:
interface Article {
id: number;
slug: string;
title: string;
body: string;
publishedAt: Date;
}
type ArticleUpdate = Partial<Omit<Article, "id" | "slug">>;First Omit removes id and slug entirely. Then Partial makes the remaining fields optional. The result is a type where title and body can be provided or omitted in an update, but id and slug can never be changed through this type.
Common mistakes
Using Omit when Pick would be clearer. If you are only keeping 2 out of 15 properties, use Pick to name the 2 you want directly. Naming a couple of fields to keep is more readable than a long Omit that lists 13 exclusions.
Relying on Omit to strip properties at runtime. Omit is compile-time only. If you send a full User object to a function typed as Omit<User, "password">, the password is still there at runtime, because the type annotation only controls what the function body is allowed to read.
You still need to explicitly remove sensitive fields from the actual object before sending it to a client.
Forgetting that Omit only removes top-level properties. Like other utility types, Omit is not deep. Removing a nested field name directly does nothing, because that name is not a top-level key of the outer object. You would need to omit the whole nested object, or write a recursive type to reach inside it.
Rune AI
Key Insights
⚠ This article has a formatting issue and may not display correctly.
Our team has been notified. The content is shown as plain text below.
Frequently Asked Questions
Is Omit the same as Exclude?
What happens if I Omit a property that does not exist?
Is Omit better than Pick?
Conclusion
Omit is Pick's complement. When you want most of a type's properties and only need to remove a few, Omit is clearer than listing every field you do want. Use it for DTOs that exclude sensitive fields, form types that exclude auto-generated fields, and any type that is one or two removals away from what you need.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.