← Back to archive

Repo of the Day

ts-rest/ts-rest

Published: Jun 20, 2023

Open repository ↗

RPC-like client, contract, and server implementation for a pure REST API

Summary

ts-rest is a TypeScript library for building REST APIs where a single shared "contract" describes the endpoints, and that same contract is both implemented on the server and consumed by clients. The goal is end-to-end type safety without code generation, with Zod for runtime validation and an optional OpenAPI integration.

What it is useful for

ts-rest is useful when you want a REST API whose request shapes, response shapes, headers, and status codes are described in one place and shared between backend and frontend TypeScript code. It is relevant if you are tired of hand-writing client fetch wrappers, keeping parallel TypeScript types in sync across services, or wiring up a separate code-generation step.

The README highlights the following capabilities:

  • End-to-end type safety across client and server
  • RPC-like client-side API
  • No code generation step
  • Zod support for runtime validation of bodies, queries, and headers
  • Optional OpenAPI generation

The repository's topics indicate server-side integrations with Fastify, NestJS, and Next.js, plus client integrations with React, React Query, and Solid, which fits a typical TypeScript full-stack setup.

How engineers can use it

The README describes a three-step flow:

  1. Define the contract. Create a shared file that uses c.router to describe each endpoint. Each route specifies its HTTP method, path, query/header/body schemas (using Zod, or plain TypeScript types via c.type<T>()), and its possible response shapes keyed by status code. For example, a getPosts route declares a GET /posts endpoint with a Zod query schema for skip and take, optional x-pagination-page header, and a 200 response typed as Post[].

  2. Implement it on the server. Use s.router(contract, { ... }) to provide handlers for each route. The handler arguments and return values are type-checked against the contract, so the compiler enforces the shape of inputs and outputs.

  3. Consume it on the client. Call methods on a typed client like client.getPosts({ headers, query }). Inputs are fully typed, and the response is typed according to the contract.

The README does not include full install commands, and it points to the official Quickstart Guide for installation, framework-specific setup, and React Query hooks. Readers should follow that guide for exact package install commands and configuration. The project is released under the MIT license.