Mapping Modifiers

Adding and Removing readonly and ?

Inside a mapped type you can add (+, the default) or remove (-) the readonly and ? modifiers.

SyntaxEffect
readonly [K in keyof T]: T[K]make all readonly (same as +readonly)
-readonly [K in keyof T]: T[K]remove readonly (make mutable)
[K in keyof T]?: T[K]make all optional
[K in keyof T]-?: T[K]make all required

Example

type Mutable<T> = { -readonly [K in keyof T]: T[K] };
type Concrete<T> = { [K in keyof T]-?: T[K] };

type FrozenConfig = { readonly apiUrl: string; readonly retries?: number };

const draft: Mutable<FrozenConfig> = { apiUrl: "https://api.shopease.in" };
draft.apiUrl = "http://localhost:4000"; // allowed now

const full: Concrete<FrozenConfig> = { apiUrl: draft.apiUrl, retries: 3 };
console.log(draft, full);

Output

{ apiUrl: 'http://localhost:4000' } { apiUrl: 'http://localhost:4000', retries: 3 }

Missing Required Field

Example

Concrete removed the ?, so retries is now required (TS2741).

type Concrete<T> = { [K in keyof T]-?: T[K] };
type Config = { apiUrl: string; retries?: number };
const c: Concrete<Config> = { apiUrl: "/" };

Compiler output (tsc)

Line 3: error TS2741: Property 'retries' is missing in type '{ apiUrl: string; }' but required in type 'Concrete<Config>'.