DEV Community

Atle Frenvik Sveen
Atle Frenvik Sveen

Posted on

TypeScript types from lists

I assume you know about types in TypeScript. That is kinda the essence.

And you've probably run into situations where you want to or together different things into a type. Like me, when I want to summarize beers I like, I can say:

type AtlesKindOfBeer = 'ipa' | 'stout' | 'lambic';
Enter fullscreen mode Exit fullscreen mode

Whith this defined, I can create a function like this:

const serveAtleBeer = (beer: AtlesKindOfBeer) => console.log("Cheers");
Enter fullscreen mode Exit fullscreen mode

This means that we avoid situations like this:

serveAtleBeer('lite banana-neipa');
Enter fullscreen mode Exit fullscreen mode

But, say that you are handed a string describing a beer style, and want to check if this is a beer I like?

Typeguards to the rescue!

const isAtlesKindOfBeer = (beer: string): beer is AtlesKindOfBeer 
  => ['ipa', 'stout', 'lambic'].inludes(beer);
Enter fullscreen mode Exit fullscreen mode

This works. Kinda. See the problem? Duplication! Say that I want to add "geuze" to my list of drinkable beers. Then I have to update both the AtlesKindOfBeer type and the isAtlesKindOfBeer typeguard. And here lies a potential for fuckup. And every potential for fuckup will, someday, develop into a fuckup.

So, how do we eliminate the potential? We define the list of beers I like once. Like this:

const atlesKindsOfBeer = ['ipa', 'stout', 'lambic'] as const;
Enter fullscreen mode Exit fullscreen mode

then both the type and the typeguard can reference this list:

type AtlesKindOfBeer = typeof atlesKindsOfBeer[number];

const isAtlesKindOfBeer = (beer: string): beer is AtlesKindOfBeer 
  => atlesKindsOfBeer.inludes(beer as AtlesKindOfBeer);
Enter fullscreen mode Exit fullscreen mode

Hooray!

Btw: the as const syntax is known as a [const assertion]!(https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions)

Top comments (0)