TS-Rest

TS-Rest

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

ts-rest

Introduction

ts-rest offers a simple way to define a contract for your API, which can be both consumed and implemented by your application, giving you end to end type safety without the hassle or code generation.

Features

  • End-to-end type safety 🛟
  • RPC-like client side API ⚡️
  • Small Bundle Size 📉
  • No Code Generation 🏃‍♀️
  • Zod support for runtime validation 🔒
  • Full optional OpenAPI integration 📝

Super Simple Example

Easily define your API contract somewhere shared

const contract = c.router({
 getPosts: {
 method: 'GET',
 path: '/posts',
 query: z.object({
 skip: z.number(),
 take: z.number(),
 }), // <-- Zod schema
 responses: {
 200: c.type<Post[]>(), // <-- OR normal TS types
 },
 headers: z.object({
 'x-pagination-page': z.coerce.number().optional(),
 }),
 },
});

Fulfill the contract on your server, with a type-safe router:

const router = s.router(contract, {
 getPosts: async ({ params: { id } }) => {
 return {
 status: 200,
 body: prisma.post.findUnique({ where: { id } }),
 };
 },
});

Consume the api on the client with a RPC-like interface:

const result = await client.getPosts({
 headers: { 'x-pagination-page': 1 },
 query: { skip: 0, take: 10 },
 // ^-- Fully typed!
});

Submit a project

Comma-separated technologies