Readonly<T>
Last updated: 2026-10-22
Readonly<T> Readonly
Readonly<T> makes every property of T read-only: reassigning a property after creation is a compile error. Great for configs, snapshots and shared constants — data that should not change once built. Note it locks properties, whereas const locks the variable binding.
| Group | Utility Types |
|---|---|
| Kind | Type |
| Strict mode | Not required |
ℹ️ Info The editor transpiles TypeScript to JavaScript and runs it (no type checking); see each example's Output for type-check results.
📝 Syntax
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
// Usage
const config: Readonly<AppConfig> = { appName: "docs", port: 8080, debug: false };
// config.debug = true; // error: Cannot assign to 'debug' because it is a read-only property
⚙️ Parameters
| T | The object type to transform; the mapped type adds the readonly modifier to every property |
|---|
Returns:A new type with the same properties as T, but all marked readonly.
▶ Example
Edit the code below and click Try it to see the transpiled result:
Output:
docs-site:8080
(Runtime output after transpilation; the read-only protection is statically enforced by tsc — uncommenting that line yields error TS2540, while plain JS would happily allow the assignment)
💡 Notes
ℹ️ Info The implementation is a mapped type: [K in keyof T] prefixed with readonly. It fully erases at transpilation — there is no Object.freeze-style runtime protection.
⚠️ Note Readonly is shallow: a nested object property becomes read-only as a whole, but fields inside it stay mutable; array properties become ReadonlyArray, though object elements within remain mutable. Write DeepReadonly for deep protection.
💡 Tip Versus as const: Readonly<T> operates on an existing type (literal inference unchanged — mode is still string), while as const operates on the literal itself (mode narrows to "dark"). Use as const for literal narrowing, Readonly just to prevent mutation.
🏷️ Related Utility Types
💡 Related cases
More cases coming soon.
📚 Related tutorials
❓ FAQ
Q How does Readonly differ from Object.freeze?
A Readonly is compile-time only and disappears after transpilation (runtime mutation succeeds); Object.freeze freezes at runtime, silently (or throwing in strict mode) blocking writes. You can combine both: Readonly in types, freeze at runtime.
Q Can a readonly property be mutated through an assertion?
A Yes: (config as { debug: boolean }).debug = true compiles. That is exactly why readonly is a compile-time convention, not a runtime lock — bypassing it is abandoning protection and should be banned in team code.
Q How do ReadonlyArray and readonly T[] relate?
A They are exactly equivalent: readonly T[] is shorthand for ReadonlyArray<T>. Both ban push/pop/index assignment, and like Readonly<T> on object properties they provide shallow read-only protection.