Skip to content

Refuse to Harm Your Software Architecture in the Name of Type Safety

If you're designing your software differently than you might prefer to otherwise, all in the name of type safety, I consider that an unqualified blunder.

By Jared White

(Caveat: I’m speaking from the standpoint of building user-facing business/consumer apps for the web. Perhaps the calculus is somewhat different in another context.)

Type safety encompasses two concepts: a signal to a code author how to use an API as its creator intended, and a signal to a compiler that the code supplied to it will work as its author intended. In theory, I have no problem with either of these concepts.

What really grinds my gears however is when I see people making design decisions on how to architect their software specifically based on type safety concerns. That’s as backwards as making design decisions on how to architect software based on test-driven concerns.

Oh crap, that’s a thing too, isn’t it… 😬

Inadvertently Making Your Systems Worse #

That enormous can of worms aside, what I’m trying to emphasize is the importance of building software layer by layer based on what will best serve the goals of each layer based on first principles. One of the first principles of building software for the web is “use the platform”. Because the web is so flexible, and we’ve gotten so used to building our own abstracted build tooling on top of the web, the “use the platform” first principle often gets overlooked. Thankfully, there’s a growing number of people advocating for an industry-wide reset. Using “vanilla” anything (HTML, CSS, JavaScript, etc.) is no longer considered something to shy away from or be suspicious of, but rather lauded and embraced.

Nevertheless, you still see some real head-scratchers out there—the most recent of which promoted “type safety” to bolster its sales pitch. I was reading an article which highlighted the dangers of typos in a block of CSS code: it was referencing a CSS Variable which didn’t exist (an incorrect usage of spaceing vs spacing). The solution was to…well, use TypeScript objects. (⁉️) So instead of writing actual, vanilla CSS like this: padding: var(--spacing-2), you should write: rcss.p(2). Literal quote from the article: “Thanks to TypeScript support, we get a great IDE integration and safety guarantees (no more typos!)”

That is a terrible solution to a real problem.

Here’s how I would have solved the problem. Find (or write) a linter which evaluates CSS Variable usage throughout the codebase and warns if a variable is used which can’t be found in the list of approved design tokens.

Note two aspects of what I’m describing here:

Now before you rush to remind me adding a linter like this wouldn’t provide one other benefit of the TypeScript Object approach which is IDE autocompletion/hover documentation, let me remind you that CSS Variables are The Web. If you aren’t able to adjust your IDE used for building a website or your team’s development workflow to accommodate understanding and utilizing a core feature of the web (CSS Variables), you have much bigger problems to worry about.

Ignoring or abusing core web features (HTML & CSS are routinely the casualties) in the name of anything—type safety or otherwise—is ill-advised. And this is but one example.

Bewitched by Type Safety #

Even larger and more egregious examples might be choosing one language/ecosystem over another primarily because of type safety. The most obvious demonstration of this? TypeScript. It’s literally JavaScript—but with “type safety”. You’re choosing not to use the language powering the global web frontend in its pure vanilla form, but rather a secondary language requiring specialized build tools and non-standard syntax solely on the basis of type safety.

Did no one stop to ask if there were less egregious ways to improve the JavaScript authoring experience to avoid mistakes and enhance IDE documentation, without having to radically overhaul everyone’s software architecture? Here’s what will really bake your noodle: you can actually write vanilla JavaScript, then simply add some JSDoc code comments and get most of the type-checking & IDE benefits of TypeScript for free.

Wait, what? (⁉️) Are you telling me I can write standard .js files which can be directly interpreted by JavaScript engines in the browser and beyond, while also reaping the benefits of type annotations in my code?


Seriously, why isn’t the choice of writing directly in TypeScript one that’s frowned upon except in very specific circumstances for very specific reasons if there’s clearly an alternative which has a far less problematic impact on software architecture? I’d even argue that by standardizing on JSDoc first, it actually encourages better code-level documentation by stimulating more intentional thought around the API-level purpose of functions, methods, arguments, etc. In that respect, habitually using JSDoc might actually be BETTER than raw TypeScript in most cases!

No More Type-Safe Sacred Cow #

Once more for the folks in the back: my point isn’t to disparage type safety in general or to say you should ignore it. What I’m saying is that making poor or unacceptable tradeoffs in other areas of your software architecture in the name of type safety is hugely concerning to me. I implore you to at least consider how you might otherwise choose technology stacks and architecture your codebases, and then feather in stricter type safety and/or linting as an additional slice of tooling if and where its needed. And if the tools out there simply won’t accommodate your more reasonable stance? Find (or create!) better tools.

Remember, programming languages and environments primarily serve the needs of humans, not computers. The more we demand our tools accommodate our higher-level thinking and principled stances, rather than compromise to fit lower-level computational “requirements” as dictated by disembodied theories of “correct” programming, the better.

Want to join a fabulous community of web developers learning how to use “vanilla” web specs like HTTP, HTML, CSS, JavaScript, & Web Components—plus no-nonsense libraries & tools which promote developer happiness and avoid vendor lock-in?

Join The Spicy Web Discord

It’s entirely free to get started. And we’ll soon be launching paid courses to take you even deeper down the rabbit hole, so stay tuned! Vanilla has never tasted so hot.