0

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.
Noitidart
  • 35,443
  • 37
  • 154
  • 323

1 Answers1

1

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.

Alireza Ahmadi
  • 8,579
  • 5
  • 15
  • 42
  • 1
    Wow this is really very cool! Thank you for this!! – Noitidart Jun 21 '21 at 18:04
  • But actually can we make it such that `const data` is `type Pets = 'dog' | 'cat' | 'rat'` Im trying to ensure that the array has each key present in this type. – Noitidart Jun 21 '21 at 18:06
  • 1
    When I change it to: `type Pet = 'dog' | 'cat' | 'rat' | 'mouse'; const data = ['dog', 'cat' , 'rat'] as Pet[];` its not erroring when `data` does not include `"mouse"` – Noitidart Jun 21 '21 at 18:10
  • 1
    You need to define `const` variable – Alireza Ahmadi Jun 21 '21 at 18:15
  • Thanks can you show example please, I'm not able to figure it out. – Noitidart Jun 21 '21 at 18:19
  • 1
    The important thing in that code is `as const` . see [this](https://stackoverflow.com/questions/66993264/what-does-the-as-const-mean-in-typescript-and-what-is-its-use-case) – Alireza Ahmadi Jun 21 '21 at 18:27
  • Thanks I understand const now. But my problem is `Pets` is a type I don't have control over. I want to make an array that has every const from `Pets` in it. I'm struggling with this. – Noitidart Jun 21 '21 at 18:30