Careeroza
Mapping Modifiers
Adding and Removing readonly and ?
Inside a mapped type you can add (+, the default) or remove (-) the readonly and ? modifiers.
| Syntax | Effect |
|---|---|
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>'.