Validating your inputs is important, even when the sender is an API- in the land of JSON-based data exchange, we can't guarantee which keys exist without checking.

Philipp's team uses the "Runtypes" library to solve this problem. It lets them write code like this:

r.Array(r.Record({ id: r.Number, name: r.String })).check(inputData)

This verifies that inputData is an array of objects with id fields (containing numbers), and a name field (containing strings).

For more complex validation, Runtypes lets you use add constraint functions to your types. So, for example, if you wanted to ensure a number is in the range of 0-52, you could do:

const YearIndexes = r.Number.withConstraint((n) => n >= 0 && n <= 52);

You could do that. But Phillip's co-worker wanted to find a more declarative approach that doesn't have any of those pesky function calls in it.

const YearIndexes = Union(
  Literal('0'),
  Literal('1'),
  Literal('2'),
  Literal('3'),
  Literal('4'),
  Literal('5'),
  Literal('6'),
  Literal('7'),
  Literal('8'),
  Literal('9'),
  Literal('10'),
  Literal('11'),
  Literal('12'),
  Literal('13'),
  Literal('14'),
  Literal('15'),
  Literal('16'),
  Literal('17'),
  Literal('18'),
  Literal('19'),
  Literal('20'),
  Literal('21'),
  Literal('22'),
  Literal('23'),
  Literal('24'),
  Literal('25'),
  Literal('26'),
  Literal('27'),
  Literal('28'),
  Literal('29'),
  Literal('30'),
  Literal('31'),
  Literal('32'),
  Literal('33'),
  Literal('34'),
  Literal('35'),
  Literal('36'),
  Literal('37'),
  Literal('38'),
  Literal('39'),
  Literal('40'),
  Literal('41'),
  Literal('42'),
  Literal('43'),
  Literal('44'),
  Literal('45'),
  Literal('46'),
  Literal('47'),
  Literal('48'),
  Literal('49'),
  Literal('50'),
  Literal('51'),
  Literal('52'),
  // this is the maximal amount of years prospect can be insured for in the range 18-70 years.
);
[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.