Типизация с TypeScript

Vue Router — это официальная библиотека маршрутизации для Vue.js, предоставляющая удобные средства для навигации и управления состоянием URL в приложении. При использовании TypeScript ключевой задачей является обеспечение строгой типизации маршрутов, параметров и навигационных функций, что значительно повышает надежность и предсказуемость кода.


Определение маршрутов с типами

Маршруты в Vue Router описываются объектами типа RouteRecordRaw. Для TypeScript это выглядит следующим образом:

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import Home from './views/Home.vue';
import About from './views/About.vue';

const routes: Array<RouteRecordRaw> = [
  { path: '/', name: 'Home', component: Home },
  { path: '/about', name: 'About', component: About },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

Ключевые моменты:

  • RouteRecordRaw задаёт строгую типизацию для объекта маршрута.
  • Поле name позволяет ссылаться на маршрут по имени, что важно для типизации навигации.
  • Типизация компонентов обеспечивает автодополнение и проверку наличия файлов Vue при сборке.

Типизация параметров маршрутов

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

const routes: Array<RouteRecordRaw> = [
  { path: '/user/:id', name: 'User', component: () => import('./views/User.vue') },
];

Чтобы типизировать параметр id:

import { RouteLocationNormalizedLoaded } from 'vue-router';

function getUserId(route: RouteLocationNormalizedLoaded): number {
  return Number(route.params.id);
}

Особенности:

  • Параметры маршрутов из route.params имеют тип string | undefined.
  • Преобразование в нужный тип (например, number) необходимо выполнять явно.
  • TypeScript предотвращает случайное использование несуществующих параметров.

Типизация навигации

Функции router.push, router.replace и router.resolve могут принимать как строковые пути, так и объекты с именами маршрутов и параметрами. Типизация позволяет избежать ошибок:

router.push({ name: 'User', params: { id: '123' } });

При использовании TypeScript можно создать собственные типы для параметров маршрутов:

type RouteNames = 'Home' | 'About' | 'User';

interface RouteParams {
  User: { id: string };
  Home: undefined;
  About: undefined;
}

function navigate<T extends RouteNames>(name: T, params?: RouteParams[T]) {
  router.push({ name, params });
}

navigate('User', { id: '456' });
navigate('Home'); // корректно

Преимущества:

  • Полная проверка соответствия параметров маршрута.
  • Исключение ошибок при наборе имени маршрута.
  • Автодополнение в IDE для параметров и имён маршрутов.

Использование RouteLocationRaw для типобезопасной навигации

RouteLocationRaw — это тип, описывающий аргументы, передаваемые в router.push и router.replace:

import { RouteLocationRaw } from 'vue-router';

const route: RouteLocationRaw = { name: 'User', params: { id: '789' } };
router.push(route);

Особенности:

  • Позволяет типизировать как строковые пути ('/about'), так и объекты с именами маршрутов.
  • Обеспечивает строгую проверку структуры объекта при компиляции TypeScript.

Typed Route Composables

В Composition API Vue Router предоставляет функции useRoute и useRouter. Их использование с TypeScript позволяет получить строго типизированный доступ к параметрам и методам навигации:

import { useRoute, useRouter } from 'vue-router';

const route = useRoute();
const router = useRouter();

// route.params.id имеет тип string | undefined
const userId: string = route.params.id as string;

// навигация с проверкой типов
router.push({ name: 'About' });

Для большей типовой строгости можно создать обертки:

import { RouteLocationNormalizedLoaded } from 'vue-router';

type RouteParams = {
  User: { id: string };
};

function useTypedRoute<T extends keyof RouteParams>() {
  const route = useRoute();
  return route as RouteLocationNormalizedLoaded & { params: RouteParams[T] };
}

const typedRoute = useTypedRoute<'User'>();
const id: string = typedRoute.params.id;

Генерация типов маршрутов через утилиты

В крупных проектах удобно создавать централизованные типы для всех маршрутов и параметров. Например:

export const ROUTES = {
  Home: { path: '/' },
  About: { path: '/about' },
  User: { path: '/user/:id' },
} as const;

type RouteNames = keyof typeof ROUTES;

type RouteParamsMap = {
  Home: undefined;
  About: undefined;
  User: { id: string };
};
  • as const фиксирует значения объектов и позволяет TypeScript выводить литеральные типы.
  • Центральная типизация позволяет безопасно использовать маршруты по всему приложению.

Типизация вложенных маршрутов и lazy-loading

Для вложенных маршрутов и динамической загрузки компонентов также важна строгая типизация:

const routes: Array<RouteRecordRaw> = [
  {
    path: '/dashboard',
    component: () => import('./views/Dashboard.vue'),
    children: [
      { path: 'stats', name: 'Stats', component: () => import('./views/Stats.vue') },
      { path: 'settings', name: 'Settings', component: () => import('./views/Settings.vue') },
    ],
  },
];

Особенности:

  • Каждый вложенный маршрут типизируется как отдельный RouteRecordRaw.
  • Автодополнение имён маршрутов работает и для дочерних маршрутов.
  • Lazy-loading компонентов с () => import(...) сохраняет типизацию и предотвращает ошибки в пути к компоненту.

Интеграция с Vuex или Pinia

При использовании TypeScript и Vue Router с состоянием приложения (Vuex или Pinia) можно обеспечить полную типовую совместимость:

import { useUserStore } from './stores/user';
import { useRouter } from 'vue-router';

const router = useRouter();
const userStore = useUserStore();

if (!userStore.isAuthenticated) {
  router.push({ name: 'Login' });
}
  • Строгая типизация маршрутов и состояния приложения предотвращает несоответствия.
  • Автодополнение для методов и свойств хранилища повышает скорость разработки.

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