Noitidart
Noitidart

Reputation: 37228

Array of const type, no more no less values

A library I'm using exports a type like this:

type Pet = 'dog' | 'cat' | 'rat';

I want to now make a dropdown that has all these values in my UI. I am not able to enumerate this const type. So I thought to make an array of these values and type it such that it must have exactly one of each const in the type Pet but can't figure this out.

I tried the following but it doesn't cause error when more keys are added to Pet. I want typescript to fail on build when I update the lib and the lib decided to add more consts.

type Pet = 'dog' | 'cat' | 'rat';

const pets: Pet[] = ['dog', 'dog']; // this should error as its missing "cat" and "rat". and also it has "dog" twice.

Upvotes: 0

Views: 64

Answers (1)

Alireza Ahmadi
Alireza Ahmadi

Reputation: 9893

Based on this if you use TypeScript 4.1 or later you can do like this:

type UniqueArray<T> =
  T extends readonly [infer X, ...infer Rest]
    ? InArray<Rest, X> extends true
      ? ['Encountered value with duplicates:', X]
      : readonly [X, ...UniqueArray<Rest>]
    : T

type InArray<T, X> =
  T extends readonly [X, ...infer _Rest]
    ? true
    : T extends readonly [X]
      ? true
      : T extends readonly [infer _, ...infer Rest]
        ? InArray<Rest, X>
        : false


const data = ['dog', 'cat' , 'rat'] as const
const uniqueData: UniqueArray<typeof data> = data

const pets: UniqueArray <typeof data> = ['dog', 'dog']; // this should error as its missing "cat" and "rat". and also it has "dog" twice.

Here is working code.

Upvotes: 1

Related Questions