DEV Community

Cover image for Typescript: Discriminated Type Union Pattern
Kevin Toshihiro Uehara
Kevin Toshihiro Uehara

Posted on

Typescript: Discriminated Type Union Pattern

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:

type PokemonState = {
  status: "Loading" | "Success" | "Error";
  pokemon?: { name: number; sprite: string; hp: number };
  error?: { message: string };
};
Enter fullscreen mode Exit fullscreen mode

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:

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;
  }
};
Enter fullscreen mode Exit fullscreen mode

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

Error on Pokemon Function because of possibly undefined

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.

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

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

type PokemonErrorState = {
  status: "Error";
  error: { message: string };
};
Enter fullscreen mode Exit fullscreen mode

Now we can remove the ? can be undefined property on each state.

And Let's create our Union Type:

type PokemonNewState =
  | PokemonLoading
  | PokemonSuccessState
  | PokemonErrorState;
Enter fullscreen mode Exit fullscreen mode

and change the parameter type on our function:

Resolution Typescript and resolving the errors

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;
  }
};
Enter fullscreen mode Exit fullscreen mode

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

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

Top comments (0)