Skip to content
webtype.orgwebtype.org#249 partial-by-keys · par 3

    ↑↓ move · ⏎ open · esc close

    No. 249 · September 1, 2026 · Moderate

    Optional, but only these

    Implement `PartialBy<T, K>` so only the properties named in `K` become optional. The result must be one flat object type, not an intersection. `Flatten` is provided.

    01

    Try the puzzle yourself

    Par 3

    Puzzle

    partial-by-keys.ts
    type Flatten<T> = { [K in keyof T]: T[K] }
    Stroke 1 of 3Not run yet

    Replace ??? — your solution is checked against the cases below. Tab indents; press Escape then Tab to move focus out.

    Checks

    3
    • PartialBy<{ a: string; b: number }, 'b'>
      { a: string; b?: number }
    • PartialBy<{ a: string; b: number }, 'a' | 'b'>
      { a?: string; b?: number }
    • PartialBy<{ a: string }, never>
      { a: string }

    How a check is judged Exact type equality, not assignability — an intersection is not the same as the flattened object.

    How everyone did

    Fewer than 5 people have solved this one so far. The distribution appears once there is enough of a sample to mean anything.

    Short game

    Fewest characters

    No public scores yet.

    Archive
    02

    Annotated solution

    Published September 2, 2026

    The solution

    type PartialBy<T, K extends keyof T> = Flatten<Omit<T, K> & Partial<Pick<T, K>>>

    The common wrong answer

    type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>

    Everything about this is right except the shape. `{ a: string } & { b?: number }` accepts and rejects exactly the same values as `{ a: string; b?: number }`, but it is not the same *type*, and `Equal` compares types rather than behaviour. An intersection is two objects standing next to each other; the check asks for one.

    Line by line

    1. Omit<T, K> & Partial<Pick<T, K>>

      Split the object in two: the keys that stay as they are, and the keys that become optional. Each half is easy on its own.

    2. Flatten<...>

      A homomorphic mapping over the intersection walks every key once and rebuilds a single object — and because it is homomorphic, the `?` survives the trip.

    Takeaway

    Intersections are how you assemble an object type; a homomorphic mapping is how you finish one. Assembling without finishing is the single most common reason a correct-looking solution fails these checks.

    Uses