Что такое end-to-end типобезопасность?
Типобезопасные API гарантируют соответствие данных между сервером и клиентом во время компиляции, предотвращая ошибки времени выполнения.
Проблема традиционных подходов
При использовании REST или других протоколов часто возникает разрыв между типом данных на сервере и тем, как они интерпретируются на клиентской стороне:
// Сервер возвращает это
{ id: string, name: string, email: string }
// Клиент предполагает это (нет гарантии)
const user = await fetch('/api/user').then(r => r.json());
// Тип: any
user.naem; // опечатка - ошибка только при выполнении
Решение с tRPC
С библиотекой tRPC типы автоматически синхронизированы между фронтендом и бэкендом благодаря использованию TypeScript:
import { createTRPCReact } from '@trpc/react';
const trpc = createTRPCReact();
const user = await trpc.user.get.query({ id: '1' });
// Тип: User
user.naem; // Ошибка TypeScript сразу же
Настройка проекта
Для начала работы установите необходимые пакеты:
npm install @trpc/server @trpc/client @trpc/react-query @trpc/next zod
Затем создайте файл server/trpc.ts для инициализации tRPC:
import { initTRPC, TRPCError } from '@trpc/server';
import { getServerSession } from 'next-auth';
const t = initTRPC.context<Context>().create();
export const router = t.router;
export const publicProcedure = t.procedure;
Определение процедур
Создадим роутер пользователя (server/routers/user.ts) с запросами и мутациями:
import { z } from 'zod';
import { router, protectedProcedure, publicProcedure } from '../trpc';
export const userRouter = router({
// Запрос (аналог GET)
get: publicProcedure.input(z.object({ id: z.string() })).query(...),
// Мутация (аналог POST/PUT/DELETE)
update: protectedProcedure.input(z.object({ name: z.string().min(1).max(100), bio: z.string().max(500).optional() })).mutation(...),
});
Таким образом, tRPC позволяет создавать безопасные API, которые не ломаются во время выполнения за счет строгого контроля типов.