Use Pick and Omit to Narrow JSON-Generated Types

Use json to typescript with Pick and Omit to derive list-view and detail-view subsets from a full resource type without duplication.

TypeScript Patterns

Detailed Explanation

Pick and Omit in Practice

The same backend resource often appears in multiple shapes: a full detail object on the show page, a slim summary on the list page, and a tiny avatar tooltip. Pick and Omit derive each shape from one source.

Base JSON

{
  "id": 1,
  "name": "Alice",
  "email": "alice@example.com",
  "avatar_url": "https://cdn.example.com/a.jpg",
  "bio": "Full-stack dev",
  "role": "admin",
  "created_at": "2024-01-15T08:00:00Z",
  "last_seen_at": "2024-03-20T12:00:00Z"
}

Generated Base Type

interface User {
  id: number;
  name: string;
  email: string;
  avatar_url: string;
  bio: string;
  role: "admin" | "editor" | "viewer";
  created_at: string;
  last_seen_at: string;
}

Three Derived Views

// List row — only what the table displays
type UserListItem = Pick<User, "id" | "name" | "email" | "role">;

// Avatar component props — minimal subset
type UserAvatar = Pick<User, "id" | "name" | "avatar_url">;

// Public profile — exclude sensitive timestamps
type PublicProfile = Omit<User, "email" | "last_seen_at">;

Why Pick Beats Re-Declaring

Re-declaring { id: number; name: string; email: string } in three places becomes a maintenance burden the moment id changes from number to string. With Pick, the change propagates automatically.

Pick vs Omit Heuristic

  • Use Pick when the subset is small relative to the full type (3 of 12 fields).
  • Use Omit when you exclude a few fields from a large type (10 of 12 fields).
  • Combine them: Pick<Omit<User, "password">, "id" | "name"> removes a field first, then narrows.

Type-Level Tests

To prove your derived types stay correct as the base evolves, add static assertions:

type AssertEqual<A, B> = A extends B ? (B extends A ? true : false) : false;
const _check: AssertEqual<keyof UserListItem, "id" | "name" | "email" | "role"> = true;

If someone later renames name to displayName on User, the _check line fails to compile and surfaces every dependent view.

Use Case

Reusing a single User interface generated from your API across a list page, an avatar tooltip, and a public profile page without re-declaring overlapping field sets.

Try It — JSON to TypeScript

Open full tool