Typescript: Discriminated Type Union Pattern
Tags: typescript, javascript, pattern, beginners
Published: 2023-11-27 00:35:26

Hi people! How you've been? Is it everything alright?

Today let's talk about some interesting pattern in Typescript and I will blow your mind! This pattern is called `Discriminated Type Union` or `Discriminated Union Type`.

Before I deep dive on this patter, we need to undestand the problem.

I will write some code with you:

```ts
type PokemonState = {
  status: "Loading" | "Success" | "Error";
  pokemon?: { name: number; sprite: string; hp: number };
  error?: { message: string };
};
```

So I created a type called `PokemonState`, which contains `status`, `pokemon` with some properties and `error` with a message.

Now notice, that `pokemon` and `error`, depends of the status, so it will be can be `undefined`.

If the status is `Loading`, just return the status.
If the status is `Success`, just return the pokemon.
If the status is `Error`, just return the error message.

So Let's create a function with a switch on state:

```ts
const printPokemon = (pokemonState: PokemonState) => {
  switch (pokemonState.status) {
    case "Loading":
      console.log(pokemonState.status);
      break;
    case "Success":
      console.log(pokemonState.pokemon.name, pokemonState.pokemon.sprite, pokemonState.pokemon.hp);
      break;
    case "Error":
      console.log(pokemonState.error.message);
      break;
    default:
      break;
  }
};
```

But I will show what I'm seeing on the VSCode with typescript validation:

![Error on Pokemon Function because of possibly undefined](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh2a2i9azoemklh9f8ra.png)

And heeeey! Typescript type safe validation is here!
How I said, `pokemon` and `error`, depends of `state`. We can create some logic on our function validating each status and define if we have our properties. But it's not the best solution.

But now enters ouw pattern, called `Dicriminated Type Union`. 
Let's refact our type State on three types based on our state.

```ts
type PokemonLoading = {
  status: "Loading";
};

type PokemonSuccessState = {
  status: "Success";
  pokemon: { name: number; sprite: string; hp: number };
};

type PokemonErrorState = {
  status: "Error";
  error: { message: string };
};
```
Now we can remove the `?` can be undefined property on each state.

And Let's create our Union Type:

```ts
type PokemonNewState =
  | PokemonLoading
  | PokemonSuccessState
  | PokemonErrorState;
```

and change the parameter type on our function:


![Resolution Typescript and resolving the errors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lbtfjzws7gcf4aqv4ey.gif)


```ts
const printPokemon = (pokemonState: PokemonNewState) => {
  switch (pokemonState.status) {
    case "Loading":
      console.log(pokemonState.status);
      break;
    case "Success":
      console.log(pokemonState.pokemon.name, pokemonState.pokemon.sprite, pokemonState.pokemon.hp);
      break;
    case "Error":
      console.log(pokemonState.error.message);
      break;
    default:
      break;
  }
};
```

Now is we applied the pattern on Discriminated Type Union. Now we can understand why this pattern is called with union type.

With a common property, we can separate in another types and make typescript undestand that is type safe.

I love this pattern and blow my mind how typescript can validate and turn our code more clean and understandable.

So that's it!
I hope that you enjoyed and liked of this tip/pattern on typescript.


![I love it meme gif the office](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/im3y8m6heh6zb1pvokia.gif)

Thank you so much. And stay well always! ❤️

Contacts:
Youtube: https://www.youtube.com/@ueharakevin/
Linkedin: https://www.linkedin.com/in/kevin-uehara/
Instagram: https://www.instagram.com/uehara_kevin/
Twitter: https://twitter.com/ueharaDev
Github: https://github.com/kevinuehara