Как вывести типы контекстов во вложенных layout без ручных интерфейсов в React Router v7
Как вывести типы контекстов во вложенных layout без ручных интерфейсов в React Router v7 Если вы используете TanStack Router (React Router v7) с вложенными layout, то наверняка сталкивались с ситуацией, когда родительский layout прокидывает loader-контекст, а дочерний компонент вынужден вручную объявлять интерфейс и кастить. Типовая ошибка — забыть обновить интерфейс при изменении структуры данных, что ведет к багам на проде. Как работает типовая цепочка Система типов строится вокруг дженериков createRoute. Каждый роут наследует контекст от родителя через getParentRoute(). TypeScript автоматически мержит результаты loader родительского и текущего роута: const rootRoute = createRootRoute()({ loader: () => ({ user: 'John' }) }); const layoutRoute = createRoute({ getParentRoute: () => rootRoute, loader: ({ context }) => ({ theme: context.user === 'John' ? 'dark' : 'light' }) }); const pageRoute = createRoute({ getParentRoute: () => layoutRoute, loader: ({ context }) => { // context: { user: string, theme: string } return context.theme; } }); Ни одного явного интерфейса или каста. Система выводит тип контекста из цепочки родительских роутов. Production-кейс: аутентификация с правами Практический пример: вложенный layout с авторизацией. Родитель кладет user, дочерний — permissions: const authLayout = createRoute({ getParentRoute: () => rootRoute, loader: () => ({ user: fetchUser() }) }); const adminLayout = createRoute({ getParentRoute: () => authLayout, loader: ({ context }) => ({ permissions: fetchPermissions(context.user.id) }) }); Страница получает { user, permissions } без ручного объявления. Если переименовать user в currentUser — TypeScript подсветит все места, где используется старый ключ. Типичная ошибка и trade-off Ошибка: ручное объявление interface IContext = { user: string } и последующий as any при несоответствии. Это ломает всю type-safety и ведет к runtime-ошибкам при изменении данных. Trade-off: полагаться на вывод типов чуть сложнее читать в IDE, чем явные интерфейсы, но выигрыш в надежности при рефакторинге — код сам документирует контракты, и компилятор ловит несоответствия. Вывод: Используйте автоматический вывод типов контекстов через цепочку getParentRoute, чтобы избавиться от ручных интерфейсов и кастингов, повысив надежность и упростив рефакторинг в production-коде.