Avoid Optional Chaining and Optional Properties
Functional Programmers learn pretty early that Maybe/Optional should be avoided if possible. While many languages have lifting abilities to make them easier to work with, they end up littering your code with multiple places you have to handle the case where the data simply isn’t there. This is one of the reasons you see “Parse, Don’t Validate” pushed so heavily; you no longer have to write so many unhappy paths in the code, just 1 in the beginning. It’s clear many JavaScript/TypeScript developers who utilize optional chaining like “thing | undefined”, or worse optional properties, “property?: thing | undefined” haven’t learned this painful lesson. It may look flexible, having multiple classes/functions capable of handling undefined, each with multiple paths in them, but it has a pretty negative set of costs. The more code you add, the more additional code you must add to handle the undefined scenario. Most can’t be handled anyway, and end up returning or throwing errors. This also makes it difficult to handle data in an immutable way, and can lead to the temptation to “just make an Object here to fix the problem down the line”. This then causes you to start getting weird bugs that only happen in some code paths. Act like Go; if the data isn’t there, error early. Save the rest of your code base from dealing with ambiguity. Create types that don’t have “data | undefined”, and avoid the types that have properties that could possibly not exist like “name?: string”. If that’s the style of JSON you get back from something you don’t control, no problem; parse it with something like Zod, or manually validate the data you need is there, with defaults if you have them, and then create a new type that has everything you need. If you can’t, error. Your future self will thank you.

Functional Programmers learn pretty early that Maybe/Optional should be avoided if possible. While many languages have lifting abilities to make them easier to work with, they end up littering your code with multiple places you have to handle the case where the data simply isn’t there. This is one of the reasons you see “Parse, Don’t Validate” pushed so heavily; you no longer have to write so many unhappy paths in the code, just 1 in the beginning.
It’s clear many JavaScript/TypeScript developers who utilize optional chaining like “thing | undefined”, or worse optional properties, “property?: thing | undefined” haven’t learned this painful lesson. It may look flexible, having multiple classes/functions capable of handling undefined, each with multiple paths in them, but it has a pretty negative set of costs. The more code you add, the more additional code you must add to handle the undefined scenario. Most can’t be handled anyway, and end up returning or throwing errors. This also makes it difficult to handle data in an immutable way, and can lead to the temptation to “just make an Object here to fix the problem down the line”. This then causes you to start getting weird bugs that only happen in some code paths.
Act like Go; if the data isn’t there, error early. Save the rest of your code base from dealing with ambiguity. Create types that don’t have “data | undefined”, and avoid the types that have properties that could possibly not exist like “name?: string”.
If that’s the style of JSON you get back from something you don’t control, no problem; parse it with something like Zod, or manually validate the data you need is there, with defaults if you have them, and then create a new type that has everything you need. If you can’t, error. Your future self will thank you.