TypeScript: checking at compile time if an Array lists all property keys

[2022-07-27] dev, typescript
(Ad, please don’t block)

In this blog post, we use TypeScript to ensure that an object stays in sync with an Array that lists its properties.

The problem  

Consider the following TypeScript code:

interface Person {
  first: string;
  last: string;
}

const personKeys = [
  'first',
  'last',
] as const;

personKeys lists the property keys of Person. Can we check at compile time if this list is correct?

The solution  

import {assert as tsafeAssert, Equals} from 'tsafe';
tsafeAssert<Equals<
  keyof Person,
  (typeof personKeys)[number]
>>();

Library tsafe enables us to check if two types are equal.

The arguments of Equals<> are computed as follows:

// %inferred-type: "first" | "last"
type A = keyof Person;

// %inferred-type: readonly ["first", "last"]
type B = typeof personKeys;

// %inferred-type: "first" | "last"
type C = B[number];

To compute type C, we are using the indexed access operator T[K]: For a given type T, it computes the types of all properties whose keys are assignable to type K. The following two types are roughly equivalent. That explains the result of computing B[number].

type T = ["first", "last"];
type U = {
  0: "first",
  1: "last",
};

Further reading