Skip to content

    ↑↓ move · ⏎ open · esc close

    TS2542

    Read-only index signature

    Index signature in type '{ readonly [k: string]: number; }' only permits reading.

    The compiler’s own words. Not translated — this is the string you pasted into a search box.

    The object accepts any string key, and every one of them is read-only. This is TS2540 applied to a whole family of keys at once.

    Reproduction

    declare const ro: { readonly [k: string]: number }
    
    ro.x = 1

    The build asserts this emits exactly this code.

    Why the compiler says this

    A `readonly` index signature is how you describe a lookup table that must not be edited in place — a frozen config, a memoised map you hand out, the result of a mapping you do not want mutated. The modifier applies to keys that do not exist yet, which is the part that surprises people: there is no key you can invent that will be writable.

    Fixes

    1. 01
      declare const ro: { [k: string]: number }
      
      ro.x = 1

      Drop `readonly` if the table really is meant to be edited.

    2. 02
      declare const ro: { readonly [k: string]: number }
      
      const next: { readonly [k: string]: number } = { ...ro, x: 1 }

      Or spread into a new one. The original stays valid for everyone still holding it, which is the reason it was `readonly` in the first place.

    Takeaway

    `readonly` on an index signature is a statement about every key, present and future. It is the strongest immutability the type system offers, and it still disappears at run time.

    Where to go next

    Errors