Skip to content
webtype.orgwebtype.org#236 getters · par 3

    ↑↓ move · ⏎ open · esc close

    No. 236 · August 19, 2026 · Moderate

    Getters

    Implement `Getters<T>` so each property becomes a zero-argument method named `get` plus the capitalised key, returning the original value type.

    01

    Try the puzzle yourself

    Par 3

    Puzzle

    getters.ts
    interface Person {
      name: string
      age: number
    }
    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
    • Getters<Person>
      { getName: () => string; getAge: () => number }
    • Getters<{ id: number }>
      { getId: () => number }
    • Getters<{}>
      {}

    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 20, 2026

    The solution

    type Getters<T> = {
      [K in keyof T as `get${Capitalize<K & string>}`]: () => T[K]
    }

    The common wrong answer

    type Getters<T> = {
      [K in keyof T as `get${K & string}`]: () => T[K]
    }

    Everything is right except the case: this produces `getname` and `getage`. Concatenation alone does not capitalise, and in camelCase method names that single character is the whole convention.

    Line by line

    1. K & string

      `keyof T` can include `symbol` and `number`, neither of which `Capitalize` accepts. Intersecting with `string` narrows the key to the part that can be interpolated, and silently drops the rest.

    2. () => T[K]

      The value becomes a function type while the key is being rewritten. Both halves of the property change in the same mapping, which is why this needs no second pass.

    Takeaway

    Key remapping composes with everything else in the type system: template literals, the intrinsic case types, and conditionals all work inside an `as` clause. This is how ORMs and event-emitter types generate their APIs.

    Uses