typescript generics series - readonly

basic technics - readonly

As you propably now, we can easily add readonly to any key of an object in typescript.

type User = {
    readonly id: string
    name: string
}

But how can we do that in generics? It is quite easy but the syntax first confused me. We simply can add or substract the keyword to any key of an object.

add readonly#

To add readonly to all keys we just add they keyword +readonly or even shorter readonly in an property iteration.

type Readonly<T> = {
  readonly [K in keyof T]: T[K];
};

That results in the same result as the utility type Readonly<Type> which exists sincce ypescript 2.1

substract readonly#

To remove all readonly keywords from a type, we do the reverse as before. We substract the keyword. So instead of prefixing all keys with readonly we basically substract the readonly keyword with -readonly.

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

More about the substracting/adding of modifieres you can read in the offical documentation for mapping-modifiers.

only make given keys readonly#

No we look into a more advanced usecase. What if we just want to mark given keys as readonly? We split that problem into two types:

  1. A type containing all keys were the type stays the same.
  2. A type where we mark all given keys as readonly.

After that we simple combine them to one single type.

type ConditionalReadonly<T, K extends keyof T> = Omit<T, K> & {
  readonly [P in K]: T[P];
};

or if you want to just use a version build on utility types:

type ConditionalReadonly<T, K extends keyof T> = Omit<T, K> & Readonly<Pick<T, K>>;

summary#

This should give you a good starting point, how to work with readonly in typescript. There are some good challenges on the “typescript challenges” sites. More on learnings and approaches to solves these puzzles see in the main articel. My approach to the typescript challenges