The Omit utility type removes properties from a type:
interface User {
id: number;
name: string;
email: string;
password: string;
}
type PublicUser = Omit<User, 'password'>;
// { id: number; name: string; email: string; }
PublicUser has all User properties except password.
Basic Syntax
Omit<Type, Keys>
-
Type: The original type -
Keys: String literal or union of property names to exclude
Omitting Single Property
interface Product {
id: string;
name: string;
price: number;
internalNotes: string;
}
type PublicProduct = Omit<Product, 'internalNotes'>;
// { id: string; name: string; price: number; }
Omitting Multiple Properties
Use a union type:
type UserWithoutSensitiveData = Omit<User, 'password' | 'email'>;
// { id: number; name: string; }
Common Use Cases
API responses without internal fields:
interface InternalUser {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
internalNotes: string;
}
type APIUser = Omit<InternalUser, 'password' | 'internalNotes'>;
Form data without auto-generated fields:
interface Article {
id: string;
title: string;
content: string;
createdAt: Date;
updatedAt: Date;
}
type ArticleFormData = Omit<Article, 'id' | 'createdAt' | 'updatedAt'>;
// { title: string; content: string; }
Update types without readonly fields:
interface Config {
readonly version: string;
apiUrl: string;
timeout: number;
}
type MutableConfig = Omit<Config, 'version'>;
// Can modify apiUrl and timeout, but not version
Omit vs Pick
Pick selects properties. Omit excludes them:
type WithPick = Pick<User, 'id' | 'name'>;
// { id: number; name: string; }
type WithOmit = Omit<User, 'email' | 'password'>;
// { id: number; name: string; }
Same result, different approach. Use Pick when selecting few properties. Use Omit when excluding few properties.
Combining with Other Utility Types
Omit + Partial:
type OptionalExceptId = { id: string } & Partial<Omit<User, 'id'>>;
// { id: string; name?: string; email?: string; password?: string; }
Omit + Required:
interface PartialUser {
id?: number;
name?: string;
email?: string;
}
type RequiredExceptId = Omit<PartialUser, 'id'> & Required<Pick<PartialUser, 'id'>>;
// { id: number; name?: string; email?: string; }
Function Parameter Types
Create parameter types by omitting irrelevant fields:
interface User {
id: number;
name: string;
email: string;
createdAt: Date;
}
function createUser(data: Omit<User, 'id' | 'createdAt'>) {
return {
id: generateId(),
createdAt: new Date(),
...data
};
}
createUser({ name: 'Alice', email: 'alice@example.com' });
Extending Omitted Types
Build on an omitted type:
interface BaseEntity {
id: string;
createdAt: Date;
updatedAt: Date;
}
interface Article extends Omit<BaseEntity, 'id'> {
id: number; // Override id to be number instead of string
title: string;
content: string;
}
How Omit Works Internally
TypeScript implements Omit using Pick and Exclude:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
-
keyof Tgets all property names -
Exclude<keyof T, K>removes the specified keys -
Pickselects the remaining properties
Edge Cases
Omitting non-existent property:
type Test = Omit<User, 'nonExistent'>;
// Works - just returns User unchanged
TypeScript doesn't error on omitting properties that don't exist. This can hide typos.
Omitting all properties:
type Empty = Omit<User, 'id' | 'name' | 'email' | 'password'>;
// {} - empty object type
Generic Functions with Omit
function updateRecord<T extends { id: string }>(
id: string,
data: Omit<T, 'id'>
): T {
return { id, ...data } as T;
}
const user = updateRecord<User>('123', {
name: 'Alice',
email: 'alice@example.com',
password: 'secret'
});
Discriminated Unions
Omit with union types:
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number };
type ShapeWithoutKind = Omit<Shape, 'kind'>;
// { radius: number } | { width: number; height: number }
Real-World Example: API Client
interface BlogPost {
id: string;
title: string;
content: string;
authorId: string;
createdAt: Date;
updatedAt: Date;
}
class BlogAPI {
async create(data: Omit<BlogPost, 'id' | 'createdAt' | 'updatedAt'>) {
// Server generates these fields
return fetch('/api/posts', {
method: 'POST',
body: JSON.stringify(data)
});
}
async update(id: string, data: Partial<Omit<BlogPost, 'id' | 'createdAt'>>) {
// Can update anything except id and createdAt
return fetch(`/api/posts/${id}`, {
method: 'PATCH',
body: JSON.stringify(data)
});
}
}
When Not to Use Omit
If you're omitting most properties, define a new type:
// Awkward
type UserPreview = Omit<User, 'password' | 'email' | 'phone' | 'address' | 'bio'>;
// Better
interface UserPreview {
id: number;
name: string;
}
TypeScript Version
Omit was added in TypeScript 3.5. For earlier versions, use the manual implementation:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Further Reading
The TypeScript handbook's Omit documentation covers usage and examples.
Matt Pocock's TypeScript tips include advanced Omit patterns.
The TypeScript source shows how utility types are implemented.
Omit simplifies type manipulation in TypeScript.
0 comments