TypeScript

TypeScript for a maintainable codebase

Eleven of our live products are written in TypeScript. For us this is not a preference, it is the default. With AI-assisted development, the type system matters more than it used to, not less.

The reason is simple: eyeballing generated code for correctness does not scale, and the compiler does. This page sets out what we actually expect from a type system and, just as importantly, where we stop expecting anything from it.

01

What types are for in the AI era

AI writes a function in seconds, but it does not know what the calling side expects. Type definitions turn that expectation into a contract a machine can check. If generated code breaks the contract, it fails at compile time rather than in production, where finding the same problem costs far more and usually involves a customer. That is why the first thing we write on a new project is generally the interface definitions and the data schemas.

02

Where type safety ends

TypeScript only runs at compile time. Data arriving over the network, form input and third-party responses can be anything at runtime. If you do not validate at those boundaries, the type system hands you false confidence, which is more dangerous than no confidence at all. We validate every piece of external data entering the application and trust the types everywhere else. The boundary is a design decision, so we mark it explicitly instead of leaving people to guess where it sits.

03

The cost of over-typing

Complex generics and clever type tricks can make a codebase unreadable. A year later, whoever is trying to unpick that type loses more time than the bug it was meant to prevent would ever have cost. We prefer simple, readable types. The goal is not to show off with the type system, it is that the next developer can touch the codebase with confidence and without a two-hour detour into type inference rules.

04

Sharing types end to end

When server and client share the same types, the most common source of cross-team bugs disappears. In Reveal Software, the web app, the browser extension and the admin panel all use shared types inside a single repository. When one field changes, every affected place shows up at compile time instead of needing a manual search across three separate codebases. That guarantee is what keeps a small team moving quickly on a product with several surfaces.

Questions

The things people ask before starting.

Should we migrate our existing JavaScript project to TypeScript?

If the project is actively developed, usually yes, but not in one pass. We migrate gradually, typing the data model and the external boundaries first. On a frozen project that nobody is changing, the return is low and we will tell you so.

Doesn't writing types slow development down?

It slows you slightly on day one and pays that back many times over at the first significant refactor. In AI-assisted development, types also provide an automatic checking layer over generated code, which changes the arithmetic considerably.

Who reviews the code?

Every change is read by an engineer before it is merged. The compiler catches type errors, and a human checks that the logic and the authorisation rules are correct, because those are not things a type system can verify for you.

Will our team be able to maintain the code after handover?

That is the goal. We hand over type definitions and documentation together, so the developer taking the work on can read what the code expects rather than reverse-engineering it from observed behaviour.

Contact

Looking for an engineering partner for the long haul?

A short note about the product, the timeline and who it is for is enough to start. You will hear back from the engineer who would do the work, not a sales team.

Ankara / Türkiye · Working across European and US time zones