Why code quality pays off: How Biome helped us build faster, cleaner TypeScript projects

Code quality is not the KPI clients are usually looking for—speed of delivery and costs usually top the priority list instead. From our experience, however, a neat codebase is a must. Especially when you plan to involve more than just one or two developers. What looks like a waste of time at the start leads to easier onboarding, faster bug mitigation, and higher developer satisfaction in the end. And the best solution for improving our TypeScript code quality we’ve found is Biome. You can now steal some of our know-how for your projects.

Immediate feedback on code quality

There are different approaches to improving code quality, but only one provides immediate feedback during development - linters. Some modern languages include them directly in their toolchain or compiler; however, most implementations are standalone utilities.
Linters can spot, and in some cases, directly fix code that may be nonperformant, too complex, error-prone, or just against the selected style guide. By integrating directly with code editors, they provide immediate feedback to the developer long before any code reviews or even issues in production may arise.

Strict configuration for linters is key

At Cookielab, we believe that the best approach is integrate linters with as strict configuration as possible. This enables us to teach our junior developers to learn about possible pitfalls, improving code maintainability and, most importantly, catch most of the bugs before any user has a chance to trigger them.

We have taken inspiration from tools like Rust’s Clippy and Python’s Ruff when preparing our comprehensive configuration for our most widely used language - Typescript.

From ESLint to Biome

Years ago, we had taken our first shot at a custom preset with our ESLint configuration. However, that package has laid dormant for a few years now and the whole ecosystem has moved at a rapid pace. Biome has emerged as the go-to tool for both linting and formatting of JavaScript, TypeScript and much more. And with the release of version 2 and a roadmap to a fully fleshed-out plugin ecosystem, there was not a better time to take another crack at a Cookielab preset

Thus @cookielab.io/biome-config was born. A comprehensive preset for the Biome toolchain to keep our codebases nice and tidy. The aim is to provide a consistent, performant and footgun-free experience to all developers working on our projects. Of course, Biome is not the be-all-end-all and we still love a proper code review and we do not shy away from additional tools such as SonarQube.

Ruleset for our Biome Config

When crafting this ruleset, we have taken a lot of inspiration from Tiger Style - a coding philosophy successfully utilized by the team working on the TigerBeetle database. And while the style mainly focuses on programming languages without a garbage collector, most of the principles and design goals apply to software development at large. So, let us dive in into the three core principles driving Cookielab’s Biome Config.

1. Safety — preventing bugs before code review

Code safety, in our context, does not necessarily mean code prone to malicious exploits. While this aspect is contained in this principle as well, it is more concerned with bug prevention. Many times our TypeScript code may look innocent during development or even during testing but fails spectacularly in production, leaving our users disappointed with an error message. In the better cases.

With this principle, we would like to prevent as many bugs as possible before they are event sent to a code review.

Not every piece of code that passes the TypeScript type checker is necessarily safe to run in production, unfortunately. And this is not limited just to TypeScript, pretty much every language is susceptible to this quirk of human-computer interaction. Even those with advanced type systems and helpful compilers such as Rust or Gleam. However, with our configuration we have tried to at least mitigate such cases.

In practice, our configuration forbids the usage of older unreliable constructs such as isNaN in favor of Number.isNaN and additional code the average developer may have never thought about. Like adding a radix when parsing a number value with Number.parseInt(value, 10).

Unfortunately, this aspect is currently the most under-represented in the Biome ecosystem as a whole. The common wisdom is to enforce this through a strict TypeScript configuration. Mainly with "strict": true and a myriad of additional options not contained in the strict preset. We may also provide our own TypeScript preset in the future to address this point.

2. Performance — some room for improvement

While TypeScript, and, by extension, JavaScript, are not the most performant languages in the world, performative code is still preferred over the alternative. Sadly, Biome does not provide a wide array of performance-related rules to choose from. Of course, simple rules like forbidding the use of spread [newValue, ...oldValues] in accumulators, such as reduce , is forbidden but not much else.

This domain is then left up to code reviewers and, if you are lucky, performance testing. We might not linger in this state for long, though. Biome is adding new rules to the nursery group regularly and some of them may be promoted into the performance group. However, a more potent tool might be needed - plugins. While the plugin ecosystem for Biome is still nascent, we plan to use it to cover the common performance pain points in the future.

3. Developer Experience — faster code reviews

Both of the previous principles may be mute, if there are no developers willing to follow them. If developers did not care about the overall development experience, we would still be writing assembly for the best performance. In this regard, Biome really excels. We are able enforce a unified and consistent code style across all project types - from a simple React SPA all the way to a Hono-based server.

Of course, code style is usually subjective and many-a-bike-shedding discussions can be had about it. The major advantage of Biome is that it does not provide many code formatting options and nips these prolonged discussions in the bud. And the code-style options it provides, we try to take advantage of to the fullest. Our goal is not necessarily to have the nicest style. The intention is, when presented with two possibilities, to pick the one that seems to seems to be consistent with our remaining ruleset. Which is concerned with explicitness.

Code is being read more than it is written, which leads us to enable every rule to prioritize explicitness over implicitness. For one, this makes code reviews much faster - code is much easier to reason about when you do not have to jump around files and functions to see, if a value used in a condition !value is a plain boolean or is being coerced implicitly from a different type.

What Next

We would like to continue working on and improving our configuration to match the three core principles. Be it with new Biome rules or custom plugins, we want our configuration to push our technical excellence even further. We might never reach the security or performance of other languages, but there is no reason we should not at least try.

Check the configuration out for yourself, the source code with documentation is available on Github while the package is available through NPM and don’t forget to let us know your feedback!

Why code quality pays off: How Biome  helped us build faster, cleaner TypeScript  projects
Patrik Dvořáček
FE Dev
By clicking “Accept”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.