Inksh logoContactAbout usPrivacy
Author name Hemant Bhatt

Hemant Bhatt

November 20, 2025

TypeScript Omit: The Art of Removal

Next.js Backend Handbook - Database, Server, and Routes illustrated as a coffee brewing system

Introduction

Here's something nobody tells you about programming: half the job is removing things, not adding them. TypeScript's Omit utility type understands this. It's a scalpel, not a hammer. You point at what you don't want, and it disappears.

What Is Omit?

Omit<Type, Keys> takes a type and removes specific properties from it. That's it.

example.ts
1type User = {
2 id: string;
3 name: string;
4 email: string;
5 password: string;
6};
7
8type PublicUser = Omit<User, "password">;
9// Result: { id: string; name: string; email: string; }

You had four fields. Now you have three. The password is gone.

Why does this exist? Because typing out almost-identical types is tedious. Omit lets you be productively lazy.

Omitting Multiple Properties

Want to remove more than one property? Use a union type.

example.ts
1type User = {
2 id: string;
3 name: string;
4 email: string;
5 password: string;
6 createdAt: Date;
7 updatedAt: Date;
8};
9
10type UserInput = Omit<User, "id" | "createdAt" | "updatedAt">;
11// Result: { name: string; email: string; password: string; }

The syntax is Omit<Type, "key1" | "key2" | "key3">. Straightforward.

Pro Tip:

If you're omitting more properties than you're keeping, stop. Just write a new type.

Exclude vs Omit

People confuse these. Don't be people.

Omit: For Objects

Removes properties from object types

omit-example.ts
1type User = { id: string; name: string };
2type NoId = Omit<User, "id">;
3// { name: string }

Exclude: For Unions

Removes values from union types

exclude-example.ts
1type Status = "pending" | "active" | "deleted";
2type Active = Exclude<Status, "deleted">;
3// "pending" | "active"

Deep Omit

Omit only works at the top level. Don't rely on it if you have deep nested properties. It just won't work.

nested-omit-fail.ts
1type User = {
2 id: string;
3 profile: {
4 socialLinks: { twitter: string; github: string };
5 };
6};
7
8type NoTwitter = Omit<User, "profile.socialLinks.twitter">; // ❌ Doesn't work

Common Patterns

API Responses: Hide Sensitive Fields

api-response.ts
1type UserFromDB = {
2 id: string;
3 name: string;
4 passwordHash: string;
5};
6
7type UserResponse = Omit<UserFromDB, "passwordHash">;

Form Inputs: Remove Auto-Generated Fields

form-input.ts
1type Post = {
2 id: string;
3 title: string;
4 createdAt: Date;
5};
6
7type CreatePostInput = Omit<Post, "id" | "createdAt">;

Omit vs Pick

Pick keeps properties. Omit removes them. Use whichever is shorter to write. That's it.

Using Omit

omit-approach.ts
1type User = {
2 id: string;
3 name: string;
4 email: string;
5 password: string;
6};
7
8// Removing 1 property
9type Public = Omit<User, "password">;

Using Pick

pick-approach.ts
1type User = {
2 id: string;
3 name: string;
4 email: string;
5 password: string;
6};
7
8// Keeping 3 properties
9type Public = Pick<User, "id" | "name" | "email">;

Common Mistakes

Mistake #1: Using Omit on Unions

Use Exclude instead.

mistake-1.ts
1// ❌ Wrong
2type Status = "pending" | "active" | "deleted";
3type Active = Omit<Status, "deleted">; // Doesn't work!
4
5// ✅ Right
6type Active = Exclude<Status, "deleted">; // "pending" | "active"

Mistake #2: Thinking Omit Makes Fields Optional

It doesn't. Use Partial for that.

mistake-2.ts
1// Omit removes fields, doesn't make them optional
2type User = { id: string; name: string; email: string };
3type NoId = Omit<User, "id">; // { name: string; email: string }
4
5// Partial makes fields optional
6type OptionalUser = Partial<User>; // { id?: string; name?: string; email?: string }

Mistake #3: Chaining Omit Calls

Use a union: Omit<T, "a" | "b">

mistake-3.ts
1// ❌ Verbose
2type Step1 = Omit<User, "password">;
3type Step2 = Omit<Step1, "createdAt">;
4type Step3 = Omit<Step2, "updatedAt">;
5
6// ✅ Clean
7type Clean = Omit<User, "password" | "createdAt" | "updatedAt">;

Combining Utilities

Make Remaining Fields Optional

combine-1.ts
1type User = {
2 id: string;
3 name: string;
4 email: string;
5 password: string;
6};
7
8type UpdateInput = Partial<Omit<User, "id">>;
9// { name?: string; email?: string; password?: string }

Make Remaining Fields Required

combine-2.ts
1type User = {
2 id?: string;
3 name?: string;
4 email?: string;
5};
6
7type StrictUser = Required<Omit<User, "id">>;
8// { name: string; email: string }

Remember:

Chaining more than two utilities? Write a new type.

Conclusion

  • Omit removes object properties. Exclude removes union values. Don't confuse them.
  • For multiple properties: Omit<T, "a" | "b">. For nested properties: flatten your types.
  • If it's getting complex, you're doing it wrong. Write a new type.

Now go delete something.

Happy typing!