tRPC типобезопасность

tRPC в Solid.js: Типобезопасность

tRPC представляет собой современный инструмент для создания типобезопасных API в JavaScript/TypeScript приложениях. Его основная цель — упростить разработку серверных API и интеграцию с клиентами, исключив необходимость вручную описывать типы для запросов и ответов. В отличие от REST и GraphQL, где типы часто необходимо описывать в разных местах, tRPC использует только TypeScript для создания типизированных API, что позволяет гарантировать полную совместимость между сервером и клиентом на уровне типов.

В сочетании с Solid.js tRPC может значительно улучшить процесс взаимодействия между компонентами приложения, позволяя эффективно использовать типобезопасность как на клиенте, так и на сервере.

Основы работы с tRPC

Прежде чем углубляться в типобезопасность, важно понять базовую концепцию tRPC. В традиционных подходах для создания взаимодействия между клиентом и сервером приходится описывать схему данных (например, в GraphQL) или же использовать REST API с дополнительными библиотеками для типизации. В tRPC же сервер и клиент взаимодействуют с использованием общих типов данных, без необходимости в промежуточных описаниях API.

Установка и настройка

Для начала необходимо установить tRPC и Solid.js, если они ещё не добавлены в проект:

npm install @trpc/server @trpc/client zod solid-js

Для создания API на сервере с использованием tRPC создаются процедуры, которые описывают бизнес-логику приложения. Они могут быть с типами входных и выходных данных, что и позволяет сделать систему полностью типобезопасной.

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

const appRouter = t.router({
  getUser: t.procedure.input(z.string()).query((opts) => {
    return { id: opts.input, name: 'John Doe' };
  }),
});

В примере выше создаётся процедура getUser, которая принимает строковый параметр (идентификатор пользователя) и возвращает объект с информацией о пользователе. Типы данных здесь строго определены с помощью Zod, что гарантирует правильность входных и выходных данных.

Использование tRPC с Solid.js

Solid.js — это библиотека для построения пользовательских интерфейсов, ориентированная на реактивность и высокую производительность. В сочетании с tRPC она может служить идеальной платформой для создания типобезопасных приложений с использованием современного подхода к разработке.

Для интеграции tRPC с Solid.js необходимо настроить клиентскую сторону, которая будет взаимодействовать с сервером. В Solid.js, как и в других реактивных фреймворках, данные, получаемые с сервера, должны быть привязаны к компонентам для динамического обновления UI.

Создание tRPC клиента

Для клиента создаётся экземпляр tRPC, который будет использоваться для отправки запросов на сервер. При этом типы запросов и их ответов передаются автоматически через TypeScript, что обеспечивает типобезопасность.

import { createTRPCProxyClient, httpLink } from '@trpc/client';
import { createSignal } from 'solid-js';

const trpc = createTRPCProxyClient<AppRouter>({
  links: [
    httpLink({
      url: 'http://localhost:4000/trpc',
    }),
  ],
});

const App = () => {
  const [userId, setUserId] = createSignal('');
  const [user, setUser] = createSignal(null);

  const fetchUser = async () => {
    const fetchedUser = await trpc.getUser.query(userId());
    setUser(fetchedUser);
  };

  return (
    <div>
      <input
        type="text"
        value={userId()}
        onIn put={(e) => setUserId(e.target.value)}
      />
      <button onCl ick={fetchUser}>Fetch User</button>
      {user() && <div>{user().name}</div>}
    </div>
  );
};

В этом примере создаётся компонент в Solid.js, который использует tRPC для запроса данных с сервера. Важно отметить, что типы для функции getUser автоматически передаются на клиентскую сторону. При изменении типа данных на сервере, например, при изменении структуры ответа, изменения сразу становятся видны на клиенте, что минимизирует возможность ошибок.

Преимущества типобезопасности с tRPC

Основное преимущество tRPC заключается в его возможности поддерживать типобезопасность на протяжении всего приложения — от клиентской части до серверной. Это важное отличие от традиционных решений, где приходится работать с отдельными типами для фронтенда и бэкенда.

  1. Единые типы на сервере и клиенте: Типы для запросов и ответов генерируются автоматически, что устраняет необходимость в их дублировании и повышает вероятность их согласования.

  2. Автоматическая проверка типов: Когда сервер или клиент меняют свои типы, TypeScript предупреждает о возможных несоответствиях, что предотвращает множество ошибок на этапе компиляции.

  3. Ускорение разработки: Благодаря типобезопасности снижается вероятность багов, связанных с несовпадением типов данных, что ускоряет процесс разработки.

  4. Интерактивность и производительность: В Solid.js тRPC интегрируется с реактивной системой фреймворка, позволяя автоматически обновлять UI при изменении данных, не требуя лишних запросов или манипуляций.

Строгая типизация с помощью Zod

Одним из мощных инструментов tRPC является библиотека Zod, которая используется для валидации и типизации данных. Вместо простого указания типа для данных, можно описать их структуру с помощью Zod, что добавляет дополнительный уровень безопасности.

Zod позволяет легко валидировать данные на сервере и использовать те же типы на клиенте, без необходимости писать дополнительные проверки. Например, можно создать схему для валидации входных данных, которая будет использоваться как на сервере, так и на клиенте.

import { z } from 'zod';

const userSchema = z.object({
  id: z.string(),
  name: z.string(),
});

const appRouter = t.router({
  getUser: t.procedure.input(z.string()).output(userSchema).query((opts) => {
    return { id: opts.input, name: 'John Doe' };
  }),
});

В этом примере схема userSchema используется для валидации выходных данных. На сервере выполняется проверка, что данные, возвращаемые клиенту, соответствуют ожидаемой структуре.

Ошибки и их обработка

Типобезопасность с tRPC также улучшает обработку ошибок. Когда возникает ошибка на сервере, типы данных, возвращаемых в ответе, всегда будут актуальны. Благодаря этому легко определить, какой тип ошибки произошёл, и обработать её должным образом.

const appRouter = t.router({
  getUser: t.procedure
    .input(z.string())
    .query(async (opts) => {
      try {
        const user = await getUserFromDB(opts.input);
        if (!user) {
          throw new Error('User not found');
        }
        return user;
      } catch (error) {
        throw new Error('Internal server error');
      }
    }),
});

В этом примере ошибка на сервере будет правильно обработана и типизирована, что позволяет избежать непредсказуемых результатов при взаимодействии с сервером.

Заключение

Использование tRPC с Solid.js и TypeScript позволяет создавать приложения с максимальной типобезопасностью на всех этапах разработки. От серверной логики до пользовательского интерфейса типы данных поддерживаются синхронизированными, что уменьшает количество ошибок, повышает скорость разработки и улучшает взаимодействие между компонентами. Интеграция с Zod добавляет дополнительный уровень безопасности при валидации данных, а реактивная система Solid.js обеспечивает высокую производительность при взаимодействии с сервером.