Omit<T, K> is a built-in utility type that creates an object type with every property of T except the keys listed in K. The classic use: a User type that has a password, and a public version that does not.
PublicUser stays in sync with User: add a field to User and it appears in PublicUser too, while password stays out. Omit works on types only; the destructuring in toPublic is what removes the property from the actual object.
Omitting Several Keys
The second argument is a union, so list as many keys as you need with |:
"The type without the server-generated fields" is the most common Omit in real code: one model type, with Omit deriving the input shape for create forms and API requests.
How Omit Is Defined
Omit is built from two other utility types:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Read it from the inside: keyof T is the union of all keys, Exclude<keyof T, K> removes the unwanted ones from that union, and Pick keeps the remaining keys. So Omit<User, "password"> is Pick<User, "id" | "name" | "email">. Because Pick maps over the keys of T, readonly and ? modifiers on the remaining properties are kept.
Notice the constraint: K extends keyof any, not K extends keyof T. That detail is the subject of the next section.
Omit Does Not Check That the Key Exists
keyof any is string | number | symbol, so Omit accepts any key at all, including one that T does not have. A typo compiles and removes nothing:
No error anywhere, and the password goes out in the JSON. The loose constraint was chosen on purpose when Omit was added in TypeScript 3.5. The team's reasons: in generic code the omitted keys often do not come from T (a function that merges two objects can type its rest argument as Omit<T1, keyof T2>), Exclude does not constrain its second parameter either, and a constrained version would have broken many of the hand-written Omit types projects already had. For everyday code, a stricter version catches the typo:
index.ts(10,36): error TS2344: Type '"pasword"' does not satisfy the constraint 'keyof User'.
index.ts(11,7): error TS2741: Property 'password' is missing in type '{ id: number; name: string; }' but required in type 'PublicUser'.
The first error is the one that matters: the key is checked against keyof User. The second follows from it, since nothing was omitted and PublicUser still requires password. Fix the spelling to "password" and it compiles. Many codebases define it once in a shared types file and use it instead of Omit.
Overriding a Property Type
An interface cannot extend another and change a property to an incompatible type: interface ApiUser extends User { id: string } fails with error TS2430: Interface 'ApiUser' incorrectly extends interface 'User'. Omit the property first, then declare it again:
With a type alias the same thing is an intersection: type ApiUser = Omit<User, "id"> & { id: string }. Without the Omit, the intersection User & { id: string } would give id the type number & string, which is never.
Omit on Union Types
Omit is not distributive. On a union it starts from keyof of the whole union, which contains only the keys every member shares, so the members' own properties disappear:
index.ts(8,39): error TS2353: Object literal may only specify known properties, and 'radius' does not exist in type 'NewShape'.
NewShape became { kind: "circle" | "square" }. To omit from each member separately, apply Omit inside a distributive conditional type:
T extends unknown ? ... : never is always true; it is there only to make the conditional type distribute over the union. The conditional types page explains why that works. Use DistributiveOmit whenever the type you omit from is a discriminated union.
Omitting a Nested Property
Omit only looks at the top-level keys, so Omit<Settings, "editor.wordWrap"> removes nothing (and, as shown above, does not complain). To drop a property one level down, omit the parent and add it back with its own Omit:
Settings["editor"] is an indexed access type: it names the nested object type so Omit can work on it.
Removing Properties at Runtime
Omit changes only the type. To produce an object without the properties, destructure them away, or write a small generic helper whose return type is Omit:
The helper constrains K to keyof T, so a misspelled key is an error at the call site. The copy is shallow: nested objects are shared with the original.
Omit vs Pick vs Exclude
| Works on | Keeps | Example | Result | |
|---|---|---|---|---|
Omit<T, K> | object types | every property except K | Omit<User, "password"> | { id; name; email } |
Pick<T, K> | object types | only the properties in K | Pick<User, "id" | "name"> | { id; name } |
Exclude<U, M> | union types | union members not assignable to M | Exclude<"a" | "b" | "c", "a"> | "b" | "c" |
Choose between Omit and Pick by what should happen when the source type grows. Omit includes new properties automatically, which suits "everything except the secret". Pick never includes them, which suits "exactly these fields" and is safer for anything that leaves your server. Pick checks its keys against keyof T; Omit does not.
Frequently Asked Questions
What does Omit do in TypeScript?
Omit<T, K> builds a new object type with all the properties of T except those whose keys are in K. Omit<User, "password"> is User without password. It only changes the type; it does not remove anything from an object at runtime.
How do I omit multiple properties in TypeScript?
Pass a union of keys as the second argument: Omit<User, "password" | "createdAt" | "updatedAt">. Every key in the union is removed.
What is the difference between Omit and Exclude?
Omit removes properties from an object type: Omit<{ a: 1; b: 2 }, "a"> is { b: 2 }. Exclude removes members from a union type: Exclude<"a" | "b", "a"> is "b". Omit is implemented with Exclude: Pick<T, Exclude<keyof T, K>>.
Why doesn't Omit give an error for a key that does not exist?
Its key parameter is constrained to keyof any (any string, number or symbol), not to keyof T, so a typo like Omit<User, "pasword"> compiles and removes nothing. Define type StrictOmit<T, K extends keyof T> = Omit<T, K> to get an error for unknown keys.
How do I remove a property from an object at runtime in TypeScript?
Use destructuring with a rest element: const { password, ...rest } = user;. TypeScript types rest as the object without password, the same shape as Omit<User, "password">, and the property is really gone from the new object.