programming.protips.wiki
githubtwitter
/assert-type-conditions
#types

Use assertions for possibly null values

Use assert or if statements to refine a type when passing a possibly null or undefined value to a function.

This is a subset problem of "don't try and outsmart the typechecker".

Bad:

function printMenu({ favoriteFoods }) {
  // $FlowFixMe: favoriteFood should always be set!
  const menu = getMenu(favoriteFoods);

  // print the menu!
  console.log(`Today's menu is: ${menu}`);
}

Good:

import invariant from 'assert';

function printMenu({ favoriteFoods }) {
  invariant(Array.isArray(favoriteFoods), 'expected favoriteFoods to be set!');
  const menu = getMenu(favoriteFoods);

  // print the menu!
  console.log(`Today's menu is: ${menu}`);
}

Also Good:

function printMenu({ favoriteFoods }) {
  if (!Array.isArray(favoriteFoods)) {
    throw new Error('expected favoriteFoods to be set!');
  }

  const menu = getMenu(favoriteFoods);
  
  // print the menu!
  console.log(`Today's menu is: ${menu}`);
}

Why?

Despite the type for a value being nullable, as humans, we may know that it may be guaranteed to be set in certain situations. But the type system doesn't - so you may be tempted to disable the type checker in such situations. Don't!

In general, we should avoid trying to "outsmart the typechecker" (see "don't try and outsmart the typechecker").

There's no real proof or guarantee the code will behave the way you expect - just your word for it. The best way to guarantee this expectation is to enforce it via the code.

The benefits here are:

  • provides a runtime check in case the expectation is violated, forcing the code to do the right thing rather than failing silently
  • provides a regression test to prevent this expectation from changing over time as the codebase evolves
  • removes the need to manually override the typechecker

Further reading