Introduction

Type safety is crucial in programming because it helps catch errors at compile-time rather than runtime, ensuring early detection and prevention of potential bugs. I’m sharing the stack that I’m using both in frontend and backend to achieve a fully-typed tech stack.

Frontend

UI Library / Framework

My pick for this is React. Having tried the big 3 frontend frameworks, it’s the only one that works very well with Typescript without the need for installing hacky extensions just to work well with your editor.

Router

For the router, I picked the new library in town TanStack Router. The sole reason is for it’s typesafety. No more searching and replacing when refactoring routes.

Fetching

For fetching stuff from the internet, I just use the vanilla fetch API functionality available natively in your browser and also the TanStack Query for managing data.

Forms and Validation

For this, I use a combination of react-hook-form for the form library and I use typebox for validation. Both are stitched to work together by @hookform/resolvers. This libraries allows me to have fully typed forms and validations.

Backend

Runtime

The runtime I picked in this stack is Bun. It just works out of the box with typescript without installing additional compiler like tsc just to compile and run your typescript code. It’s also very fast and I can attest to it’s performance compared to Node. On top of that, it also has a very fast testing suite that is very similar to jest but much faster. This also serves as the build tool for the backend

Server

For this, I picked Elysia. The reason is it’s fully typed compared to other libraries and frameworks and it’s also very simple compared to something like nestjs. It also works on Bun out of the box and heavily supported it.

Database

For the databse, I picked Keysley for it’s simplicity compared to alternatives. It’s just basically knex but for typescript. To generate the types for the database, I use it’s cli tool kysely-codegen. I did not use ORMs like TypeORM or Sequelize as they can be pretty hard to work with once the queries start to get complex. Here’s a good blog post on why it’s a bad idea.

Stitching Frontend and Backend API

Standard

I’m just using regular REST for its simplicity. For the API standard, use OpenAPI. It will allow you to generate types for your frontend.

Backend API Types

To make the consumers of this API have documentation and provide them the capability to generate types, I’m using the Swagger plugin in Elysia.

Frontend API Types

For the generating API types, use open-api-typescript with the combination of openapi-fetch. This is the simplest combination of libraries I can muster and I’m pretty happy with this.

Summary

  • Frontend
    • React
    • TanStack Router
    • TanStack Query
    • react-hook-form
    • typebox
  • Backend
    • Elysia
    • Keysley
    • Bun
  • API
    • OpenAPI
    • open-api-typescript
    • openapi-fetch
    • Elysia Swagger

Conclusion

I’m satisfied with the stack, which is fully typed, but there’s some ’type fatigue’ from coding numerous types. However, it’s worth it to prevent errors, especially in large and complex projects.