Skip to content
#242 merge-objects · par 3

    ↑↓ move · ⏎ open · esc close

    No. 242 · August 25, 2026 · Moderate

    Merge

    Implement `Merge<A, B>` so it combines two object types into one flat object. Where both define a key, `B` wins.

    01

    Try the puzzle yourself

    Par 3

    Puzzle

    merge-objects.ts
    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

    4
    • Merge<{ a: string }, { b: number }>
      { a: string; b: number }
    • Merge<{ a: string }, { a: number }>
      { a: number }
    • Merge<{}, { a: 1 }>
      { a: 1 }
    • Merge<{ a: 1 }, {}>
      { a: 1 }

    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 August 26, 2026

    The solution

    type Merge<A, B> = {
      [K in keyof A | keyof B]: K extends keyof B
        ? B[K]
        : K extends keyof A
          ? A[K]
          : never
    }

    The common wrong answer

    type Merge<A, B> = A & B

    An intersection is not a merge. For disjoint keys it is merely the wrong *shape* — assignable to the answer but not equal to it. For a shared key it is actively wrong: `{ a: string } & { a: number }` demands a value that is both, so the property becomes `never` instead of letting `B` override `A`.

    Line by line

    1. K in keyof A | keyof B

      Mapping over the union of both key sets is what produces a single flat object. Because the key set is computed rather than a bare `keyof T`, this mapping is not homomorphic — modifiers from either source are dropped.

    2. K extends keyof B ? B[K]

      Precedence is expressed by order. Testing `B` first means a shared key resolves to `B`’s type and `A` is never consulted; swapping the two branches would give you an `A`-wins merge for free.

    Takeaway

    Intersection composes constraints; merging replaces them. They coincide only when the key sets are disjoint, which is why `A & B` seems to work right up until two objects share a field.

    Uses