Проверка типов в рантайме

В TanStack Router проверка типов в рантайме реализуется через механизмы сериализации и десериализации параметров маршрута, а также через возможность строгой типизации данных, передаваемых через маршруты. Это позволяет не только обеспечить корректность данных при навигации, но и упрощает интеграцию с TypeScript, сохраняя типовую безопасность.

Декларация типов параметров

Каждый маршрут в TanStack Router может содержать параметры пути (path parameters) и параметры запроса (search parameters). Для проверки типов в рантайме библиотека предоставляет возможность описывать схему этих параметров через функции сериализации/десериализации.

import { createRouter, Route } from '@tanstack/router';

const userRoute = new Route({
  path: '/user/:id',
  parseParams: (params) => ({
    id: Number(params.id), // проверка и преобразование параметра id в число
  }),
});

В данном примере parseParams гарантирует, что значение id будет числом. Если параметр не может быть приведён к числу, TanStack Router выбрасывает ошибку в рантайме.

Типизация search-параметров

Для query-параметров (search) используется отдельный механизм. Он также может содержать сериализацию и десериализацию.

const searchRoute = new Route({
  path: '/search',
  parseSearch: (search) => ({
    query: String(search.query || ''),
    page: search.page ? Number(search.page) : 1,
  }),
});

Здесь page автоматически приводится к числу, а при отсутствии параметра задаётся значение по умолчанию. Это предотвращает ситуации, когда компонент получает некорректный тип данных.

Валидация сложных объектов

Для более сложных объектов параметров можно использовать схемы с валидаторами, например через Zod или Yup, интегрируя их с TanStack Router:

import { z } from 'zod';

const schema = z.object({
  id: z.number().int(),
  name: z.string().min(3),
});

const validatedRoute = new Route({
  path: '/profile/:id',
  parseParams: (params) => schema.parse({
    id: Number(params.id),
    name: params.name,
  }),
});

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

Проверка данных при загрузке

TanStack Router поддерживает loaders для асинхронной подгрузки данных, где также можно реализовать проверку типов:

const profileRoute = new Route({
  path: '/profile/:id',
  loader: async ({ params }) => {
    const response = await fetch(`/api/users/${params.id}`);
    const data = await response.json();

    if (typeof data.name !== 'string' || typeof data.age !== 'number') {
      throw new Error('Некорректные данные пользователя');
    }

    return data;
  },
});

Использование такой проверки гарантирует, что компонент всегда получает данные корректного типа, и позволяет избежать runtime-ошибок.

Строгая интеграция с TypeScript

TanStack Router автоматически выводит типы параметров маршрута, если они заданы через функции сериализации/десериализации:

const route = new Route({
  path: '/item/:id',
  parseParams: (params: { id: string }) => ({
    id: Number(params.id),
  }),
});

type Params = typeof route.inferParams; // { id: number }

Тип Params будет содержать корректный тип для id, соответствующий рантайм-проверке. Это позволяет полностью синхронизировать типы на этапе компиляции и во время выполнения.

Обработка ошибок типов

Для обработки ошибок проверки типов используется система errorBoundary в TanStack Router. Она позволяет перехватывать любые ошибки, связанные с некорректными параметрами или данными:

const appRouter = createRouter({
  routeTree: rootRoute,
  defaultErrorComponent: ({ error }) => <div>{error.message}</div>,
});

Ошибки, вызванные несоответствием типов, автоматически передаются в defaultErrorComponent, что упрощает отладку и улучшает UX.

Вывод

Механизмы проверки типов в рантайме в TanStack Router объединяют серилизацию параметров, схемную валидацию и строгую типизацию с TypeScript, обеспечивая надежную и безопасную маршрутизацию. Это снижает вероятность ошибок, повышает предсказуемость поведения приложения и упрощает работу с динамическими параметрами и асинхронными данными.