Or you have a client library that you use to interact with your API, and the client library changes, and you don't even notice.
Or you change the return type of a function in a library, and you don't even know who all the callers are, but it sure would be nice if they all get a build error when they update to the latest version of your library.
Lots and lots and lots of ways for this to happen in a medium+ sized project that's been around for more than a few months. It's just another way to leverage the power of types to have the compiler help you write correct code. Most of the time most people don't mess it up, but it sure feels good to know that it's literally impossible to mess up.
function foo(customerId, itemId, orderId) {
if(!customer[customerId]) throw new Error("Customer with id=" + customerId + " does not exist");
if(!item[itemId]) throw new Error("Item with id=" + itemId + " does not exist");
if(!order[orderId]) throw new Error("Order with id=" + orderId+ " does not exist");
}
Just an example of how you can detect errors early with defensive programming.It is equivalent to newtype in haskell.
Another example somebody mentioned here is a logged in user. A function can take a user and we need to always check that the user is logged. Or we could simply create a LoggedUser type and the compiler will complain if we forget.
For Rust I wrote newtype-uuid to provide newtype wrappers over UUIDs, which has already found a couple of bugs at Oxide.
A user is free to leave and rejoin a stream, and we want to retain old data. So each user_stream has columns id, user_id, stream_id (+ others)
Issues occur when people write code like the following:
streamsService.search({ withIds: userStreams.map((stream) => stream.id), });
The issue is easily noticed if you name the “stream” parameter “userStream” instead, but this particular footgun came up _all_ the time in code review; and it also occurred with other junction tables as well. Branded types on the various id fields completely solve this mistake at design time.
type Velocity = number & { BRAND: "Velocity" }
type Distance = number & { BRAND: "Distance" }
var x = 100 as Distance