MM

How two lines of TypeScript can make a bug go from “undetected in production” to “impossible to introduce”

I recently started hosting AMA-style cafe chats with developers at various stages of their journey, about software engineering and anything else within my technical experience. Below are some notes from the chat on Nov 16th, 2022.

Imagine you feed this to your front-end i18n library:

const i18enStrings = {
  'home.title': 'Life, universe, and everything',
  'home.subtitle': 'A guide',
}

const i18itStrings = {
  'home.title': "La vita, l'universo, e tutto quanto",
  'home.subtitl': 'Una guida',
}

Challenge #1: can you guess what happens when the user switches from English to Italian?

On the user side, either of these is likely to happen:

  1. the typo hides the second string from the i18n library and the site lacks the subtitle
  2. the i18n library is smart enough to fall back on a default, and the subtitle stays in English

What’s more interesting though is what happens — or rather doesn’t happen — on the developer side:

  1. the dev environment doesn’t crash;
  2. the build doesn’t break;
  3. tests don’t break;
  4. the pre-production environment doesn’t crash;
  5. the production environment doesn’t crash.

Challenge #2: how do you fix this?

And what do you fix?

The typo isn’t the problem. The problem is that all the checkpoints on the way to prod are blind to the bug.

Ask yourself:

  1. how can I, at the very least, make future instances of this problem crash prod?
  2. better: how can I make them crash preprod?
  3. better: how can I make them break tests?
  4. better: how can I make them break the build?
  5. better: how can I make them annoy the IDE to the point that it shouts at me even before I save?

In other words: picturing an imaginary line from dev to prod going from left to right, you want shift detection and prevention/correction as left as possible. [1]

Challenge #3: how do you shift this bug to the left?

If you can write a test to guard against a problem, good.

If you can write a type, great.

Here it’s such a small diff that someone unaware of all the above could easily dismiss it as minor. Assuming English strings are the authoritative ones regarding keys:

  const i18enStrings = {
    "home.title": "Life, universe, and everything",
    "home.subtitle": "A guide"
  }

+ type I18Strings = typeof i18enStrings

- const i18itStrings = {
+ const i18itStrings: I18nStrings = {
    "home.title": "La vita, l'universo, e tutto quanto",
    "home.subtitl": "Una guida"
  }

Which results in:

error TS2322: Type '{ "home.title": string; "home.subtitl": string; }' is not assignable to type '{ "home.title": string; "home.subtitle": string; }'.
  Object literal may only specify known properties, and '"home.subtitl"' does not exist in type '{ "home.title": string; "home.subtitle": string; }'.

8   "home.subtitl": "Una guida",
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~

  1. DevOps: Shift Left to Reduce Failure ↩︎