by Timur Dautov

Implementing a Custom Utility Type: Readonly

Implement the built-in Readonly generic without using it.

Readonly is a utility type in TypeScript that allows you to create a new type by making all properties of an existing type readonly.

Syntax:

Readonly<Type>
  • Type: The type from which properties will be made readonly

Example#

type User = {
  id: number;
  name: string;
  email: string;
  age: number;
};

type ReadonlyUser = Readonly<User>;

// Equivalent to:
type ReadonlyUser = {
  readonly id: number;
  readonly name: string;
  readonly email: string;
  readonly age: number;
};

// Usage
const user: ReadonlyUser = {
  id: 1,
  name: "John Doe",
  email: "john@example.com",
  age: 30,
};

Solution#

The custom Readonly type uses a mapped type to iterate over all properties of the original type (T) and make them readonly.

type User = {
  id: number;
  name: string;
  email: string;
  age: number;
};

type MyReadonly<T> = {
  readonly [P in keyof T]: T[P];
};

// Usage
type ReadonlyUser = MyReadonly<User>;
  • keyof T: This gets the union of all property names from the type T. For User type, keyof User is "id" | "name" | "email" | "age"
  • [P in keyof T]: This creates a new type by iterating over all properties of T. For User type, [P in keyof User] is "id" | "name" | "email" | "age"
  • readonly: This makes each property readonly
  • T[P]: This retrieves the type of each property P from T. For User type, T[P] is number | string

Summary#

  • Use Readonly when you want to create a new type by making all properties of an existing type readonly
  • Use cases: Creating a new type with readonly properties from an existing type

References#