Skip to content
Get typed entries from an object

    ↑↓ move · ⏎ open · esc close

    Patterns

    How do I preserve the relationship between each key and its value while iterating `Object.entries`?

    Build a union of key/value tuples with a mapped type and keep the unavoidable assertion inside one helper.

    The recipe

    type Entry<T extends object> = {
      [K in keyof T]-?: readonly [K, T[K]]
    }[keyof T]
    
    function typedEntries<T extends object>(value: T): Entry<T>[] {
      return Object.keys(value).map(key =>
        [key, value[key as keyof T]] as unknown as Entry<T>
      )
    }
    
    const settings = { dark: true, retries: 3 }
    const entries = typedEntries(settings)

    The build compiles this and checks each result below.

    How it works

    1. 01
      readonly [K, T[K]]

      Each mapped property becomes a tuple whose value is tied to that exact key.

    2. 02
      }[keyof T]

      Indexing collapses the table into a discriminated union of entries.

    What you get

    Where it goes wrong

    Like typed keys, the assertion assumes no extra runtime properties beyond `keyof T`. Use it for objects your code owns, not unvalidated values from APIs or JSON.

    Takeaway

    A mapped object indexed by `keyof` is a precise way to build a correlated tuple union.

    See also

    Patterns