Omit<Type, Keys>

Constructs a type from Type with the named properties removed.

Signature
type Omit<Type, Keys extends keyof any> = Pick<Type, Exclude<keyof Type, Keys>>
  • Added in TypeScript 3.5

Parameters

ParameterTypeDescription
$Typeany typeThe source type to remove properties from.
$Keyskeyof any (string | number | symbol, or a union of literals)The property keys to remove. Note the constraint is `keyof any`, not `keyof Type` — any key is accepted, and keys absent from Type are silently ignored.

Return value

An object type containing every property of Type except those named in KeysA Pick over the keys of Type that remain after Exclude has removed Keys.

Errors

Nothing — the loose `keyof any` constraint means even a nonsensical key type compiles. Errors surface later, where the resulting type is used.

Changelog

  • PHP 3.5Added to lib.es5.d.ts. Before 3.5 every codebase hand-rolled its own, and those copies often used the stricter `K extends keyof T` constraint, which is why migrated code sometimes starts compiling where it used to fail.

Omit keeps every property of Type except the ones you name. It is defined in terms of the other two: Pick<Type, Exclude<keyof Type, Keys>>.

When to reach for it

  • Stripping a sensitive or internal field before a value crosses a boundary: Omit<User, "passwordHash">.
  • Modelling a create/insert payload as the row type minus its server-generated fields: Omit<Row, "id" | "createdAt">.
  • Extending a third-party props type while replacing one of its members: interface Props extends Omit<ButtonProps, "onClick"> { onClick(id: string): void }.

The typo trap

Keys is constrained to keyof any, not keyof Type. That is deliberate — it lets Omit work on union types and on types whose keys are not statically known — but it means Omit<User, "passwordhash">, with the wrong case, compiles cleanly and removes nothing. The password hash then flows straight through to your response, and no error points at the line that caused it. If that matters, write a checked wrapper: type StrictOmit<T, K extends keyof T> = Omit<T, K>.

What else trips people up

It does not distribute over unions. Omit<A | B, "k"> collapses to a single object type built from the common keys, discarding the union. Write a distributive helper if you need the variants preserved.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Build a response DTO by removing internal or secret fields from a database row type.
  • Type an insert payload as the record type minus server-generated `id` and timestamps.
  • Re-export a third-party component's props with one handler replaced by your own.

Frequently asked questions

How do I remove a property from a type in TypeScript?

Use `Omit<T, "key">`, or `Omit<T, "a" | "b">` for several. It expands to `Pick<T, Exclude<keyof T, K>>` and has been in the standard library since TypeScript 3.5.

Why does Omit not complain about a key that does not exist?

Its second type parameter is constrained to `keyof any` rather than `keyof T`, so any string, number or symbol is accepted and unmatched keys are simply ignored. Define `type StrictOmit<T, K extends keyof T> = Omit<T, K>` if you want the typo caught.

Why does Omit collapse my union type?

Because `Omit` is not distributive — it computes `keyof (A | B)`, which is only the keys common to both, and produces a single object type. Use a distributive helper such as `type DistributiveOmit<T, K extends PropertyKey> = T extends any ? Omit<T, K> : never`.

More examples

The silent typo

The first log prints `[ 'email', 'id', 'passwordHash' ]` — the hash is still in the type and still in the object, because `Omit` accepted a key that does not exist on `User`. The second prints `[ 'email', 'id' ]`. The commented-out `Broken` line is what the `StrictOmit` wrapper buys you: the typo becomes an error at the declaration instead of a leak at runtime.

Example · typescript
interface User {
  id: number;
  email: string;
  passwordHash: string;
}

// Wrong case. This compiles, and removes nothing.
type Leaky = Omit<User, "passwordhash">;

const leaky: Leaky = { id: 1, email: "[email protected]", passwordHash: "9f3c" };
console.log(Object.keys(leaky).sort());

// A checked wrapper turns the typo back into a compile error.
type StrictOmit<T, K extends keyof T> = Omit<T, K>;
// type Broken = StrictOmit<User, "passwordhash">;
//   -> Type '"passwordhash"' does not satisfy the constraint 'keyof User'

type Safe = StrictOmit<User, "passwordHash">;
const safe: Safe = { id: 1, email: "[email protected]" };
console.log(Object.keys(safe).sort());

Extending third-party props with a different handler

Prints the props object and then `deleting row_42`. Without the `Omit`, `interface RowActionProps extends ButtonProps` would be an error — an interface cannot redeclare an inherited member with an incompatible type. Removing the member first is the standard way to override one field of a props type you do not control, and `disabled` stays optional because `Omit` preserves modifiers.

Example · typescript
interface ButtonProps {
  label: string;
  disabled?: boolean;
  onClick: (event: { target: string }) => void;
}

// Keep everything, replace onClick with an id-based signature.
interface RowActionProps extends Omit<ButtonProps, "onClick"> {
  rowId: string;
  onClick: (rowId: string) => void;
}

const props: RowActionProps = {
  label: "Delete",
  disabled: false,
  rowId: "row_42",
  onClick: (id) => console.log("deleting", id),
};

console.log({ label: props.label, rowId: props.rowId, disabled: props.disabled });
props.onClick(props.rowId);

Discussion

  • Be the first to comment on this lesson.