К основному содержанию
скилл CX Codex

inertia-rails-typescript — скилл для Claude Code: настройка

Скилл настраивает строгую типизацию TypeScript в Inertia Rails для React, Vue и Svelte. Помогает исправить ошибки TS2344 и TS2339.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add inertia-rails/skills --skill inertia-rails-typescript -a claude-code
Открыть на GitHub

Что делает inertia-rails-typescript

Скилл организует глобальные типы через расширение модуля @inertiajs/core внутри globals.d.ts. Вместо ручной передачи дженериков в каждый вызов usePage() данные настраиваются один раз через интерфейс InertiaConfig. В него входят поля sharedPageProps, flashDataType и errorValueType. Переименовывать эти ключи нельзя.

Для общих данных сессии скилл предписывает использовать пространство имён auth: { user: ... } внутри SharedProps. Это предотвращает коллизии с пропсами конкретных страниц. В компонентах React для пропсов страницы допустим только алиас type Props, поскольку интерфейсы лишены индексной сигнатуры и вызывают ошибку TS2344.

Модульное расширение сработает только в файле деклараций .d.ts. Если поместить блок declare module в обычный файл .ts с импортами, компилятор TypeScript его проигнорирует.

Какие задачи решает

  • настроить глобальную типизацию общих пропсов через InertiaConfig
  • устранить ошибку TS2344 при типизации компонентов React
  • исправить ошибку TS2339 при чтении flash и auth из usePage
  • разделить типы глобальных данных Rails и пропсов конкретной страницы

Примеры запросов агенту

  • Настрой типизацию TypeScript для Inertia Rails в файле globals.d.ts
  • Исправь ошибку TS2344 в типах страницы React на Inertia
  • Добавь типизацию для уведомлений flash через usePage()

Как установить inertia-rails-typescript

1Через Skills CLI (Vercel)

npx skills add inertia-rails/skills --skill inertia-rails-typescript -a claude-code

2Вручную: положить файлы

~/.claude/skills/inertia-rails-typescript/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/inertia-rails-typescript/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о inertia-rails-typescript

Как установить inertia-rails-typescript в Claude Code?

Выполните команду npx skills add inertia-rails/skills --skill inertia-rails-typescript -a claude-code. Альтернативный вариант — скопировать файл скилла по пути ~/.claude/skills/inertia-rails-typescript/SKILL.md.

Зачем нужен скилл inertia-rails-typescript?

Он задаёт правила типизации общих пропсов, ошибок и сообщений flash для Inertia Rails без дублирования дженериков в компонентах. Подход одинаков для React, Vue и Svelte.

Почему для пропсов React-страниц нужен type, а не interface?

Дженерик usePage<T>() требует неявной индексной сигнатуры, которая есть у type, но отсутствует у interface. Использование interface приводит к ошибке TS2344.

Исходный текст

SKILL.md · MIT
---
name: inertia-rails-typescript
description: >-
  TypeScript type safety for Inertia Rails (React, Vue, Svelte): shared props, flash, and errors via InertiaConfig
  module augmentation in globals.d.ts. Use when setting up TypeScript types, configuring shared props typing, fixing
  TS2344 or TS2339 errors in Inertia components, or adding new shared data.
---

# Inertia Rails TypeScript Setup

Type-safe shared props, flash, and errors using InertiaConfig module augmentation.
Works identically across React, Vue, and Svelte — the `globals.d.ts` and `InertiaConfig` setup is the same for all frameworks.

**Before adding TypeScript types, ask:**
- **Shared props (auth, flash)?** → Update `SharedProps`/`FlashData` in `index.ts` — InertiaConfig in `globals.d.ts` propagates them globally via `usePage()`
- **Page-specific props?** → `type Props = { ... }` in the page file only — never include shared props here

## InertiaConfig Module Augmentation

Define shared props type ONCE globally — never in individual page components.

InertiaConfig property names are EXACT — do not rename them:
- `sharedPageProps` (NOT sharedProps)
- `flashDataType` (NOT flashProps, NOT flashData)
- `errorValueType` (NOT errorBag, NOT errorType)

```typescript
// app/frontend/types/globals.d.ts
import type { FlashData, SharedProps } from '@/types'

declare module '@inertiajs/core' {
  export interface InertiaConfig {
    sharedPageProps: SharedProps   // EXACT name — auto-typed for usePage().props
    flashDataType: FlashData      // EXACT name — auto-typed for usePage().flash
    errorValueType: string[]      // EXACT name — errors are arrays of strings
  }
}
```

```typescript
// app/frontend/types/index.ts
export interface FlashData {
  notice?: string
  alert?: string
}

export interface SharedProps {
  auth: { user?: { id: number; name: string; email: string } }
}
```

**Convention:** Use `auth: { user: ... }` as the shared props key — this matches the
Rails `inertia_share` community convention (`{ auth: { user: current_user } }`).
The `auth` namespace separates authentication data from page props, preventing
collisions when a page has its own `user` prop. Do NOT use `current_user:` or
`user:` as top-level keys — they collide with page-specific props and break the
convention that other Inertia skills and examples assume.

## BAD vs GOOD Patterns

```tsx
// BAD — passing shared props as generics:
// usePage<{ users: User[], auth: AuthData, flash: FlashData }>()

// BAD — extending a SharedProps interface into page props:
// interface Props extends SharedData { users: User[] }

// BAD — declaring PageProps interface:
// interface PageProps { auth: AuthData; flash: FlashData }

// BAD — using current_user or user as top-level shared key:
// interface SharedProps { current_user: User }

// BAD — destructuring auth directly from usePage() (TS2339: 'auth' does not exist on Page):
// const { auth } = usePage()
// usePage() returns a Page object with { props, flash, component, url, ... }
// auth lives inside props, not on the Page itself

// BAD — duplicating InertiaConfig in index.ts (it belongs in globals.d.ts):
// declare module '@inertiajs/core' { ... }  ← in index.ts

// GOOD — props from usePage().props, flash from usePage().flash:
const { props, flash } = usePage()
// props.auth is typed (from SharedProps via InertiaConfig)
// flash.notice is typed (from FlashData via InertiaConfig)
```

**Important:** `globals.d.ts` configures InertiaConfig ONCE. When adding a new shared
prop, only update `index.ts` — do NOT touch `globals.d.ts`:

```typescript
// BEFORE — app/frontend/types/index.ts
export interface SharedProps {
  auth: { user?: { id: number; name: string; email: string } }
}

// AFTER — add the new key here, NOT in globals.d.ts
export interface SharedProps {
  auth: { user?: { id: number; name: string; email: string } }
  notifications: { unread_count: number }
}
```

InertiaConfig in `globals.d.ts` references `SharedProps` by name — it picks up the
change automatically. Adding a second `declare module '@inertiajs/core'` causes conflicts.

## Page-Specific Props

Page components type ONLY their own props. Shared props (like auth) and flash come from
InertiaConfig automatically.

### `type` vs `interface` for page props (React-specific)

This constraint applies to **React only**. Vue's `defineProps<T>()` and Svelte's
`$props()` do not use `usePage<T>()` generics, so `interface` works fine there.

`usePage<T>()` requires `T` to have an index signature. `type` aliases have one
implicitly; `interface` declarations do not. Using `interface` with `usePage`
causes TS2344 at compile time.

| Pattern | Works with `usePage<T>()`? | Notes |
|---------|---------------------------|-------|
| `type Props = { users: User[] }` | Yes | Preferred — just works |
| `interface Props { users: User[] }` | **No** — TS2344 | Missing index signature |
| `usePage<Required<Props>>()` | Yes | Wraps interface to add index signature |

```tsx
// React
type Props = {
  users: User[]         // page-specific only
  // auth is NOT here — it comes from InertiaConfig globally
}

export default function Index({ users }: Props) {
  // Access shared props separately:
  const { props, flash } = usePage()
  // props.auth is typed via InertiaConfig
  // flash.notice is typed via InertiaConfig
  return <UserList users={users} />
}
```

### Accessing shared props in Vue and Svelte

Vue and Svelte use different patterns to access shared props, but InertiaConfig
typing works the same way.

```vue
<!-- Vue 3 — usePage() returns reactive object; use computed() for derived values -->
<script setup lang="ts">
import { usePage } from '@inertiajs/vue3'
import { computed } from 'vue'

const page = usePage()
const userName = computed(() => page.props.auth.user?.name) // typed via InertiaConfig
</script>
```

```svelte
<!-- Svelte — page store from @inertiajs/svelte -->
<script lang="ts">
  import { page } from '@inertiajs/svelte'
  // $page.props.auth is typed via InertiaConfig
  // $page.flash.notice is typed via InertiaConfig
</script>
```

## Common TypeScript Errors

| Error | Cause | Fix |
|-------|-------|-----|
| **TS2344** on `usePage<Props>()` | `interface` lacks index signature | Use `type Props = { ... }` instead of `interface`, or wrap: `usePage<Required<Props>>()` |
| **TS2339** `'auth' does not exist on type Page` | Destructuring `auth` from `usePage()` directly | `usePage()` returns `{ props, flash, ... }` — use `usePage().props.auth`, not `usePage().auth` |
| **TS2339** `'flash' does not exist on type` | Accessing `usePage().props.flash` | Flash is top-level: `usePage().flash`, NOT `usePage().props.flash` |
| Shared props untyped | Missing InertiaConfig | Add `globals.d.ts` with module augmentation (see above) |
| InertiaConfig not taking effect | Declaration in wrong file | Must be in a `.d.ts` file (e.g., `globals.d.ts`), not in `.ts` — TypeScript ignores `declare module` in regular `.ts` files that have imports/exports |
| Types correct but IDE shows errors | `globals.d.ts` not included | Verify `tsconfig.app.json` includes the types directory in `include` array |

## Typelizer Integration

If using the `typelizer` gem (see `alba-inertia` skill), SharedProps are auto-generated
from your serializer — do NOT manually write the `SharedProps` interface in `index.ts`.
You only write `globals.d.ts` once (the InertiaConfig augmentation). When you add a new
attribute to `SharedPropsResource`, Typelizer regenerates `index.ts` and the types
propagate via InertiaConfig — no manual type updates needed.

## Related Skills
- **Shared props setup** → `inertia-rails-controllers` (inertia_share)
- **Flash config** → `inertia-rails-controllers` (flash_keys)
- **Auto-generated types** → `alba-inertia` (Typelizer + Alba resources)
- **Page component props** → `inertia-rails-pages` (type Props pattern)

© inertia-rails · MIT · inertia-rails/skills

Похожие скиллы

Всё по теме «Фронтенд и UI» →
frontend-design официальный anthropics Скилл задаёт осмысленное визуальное направление для новых интерфейсов и редизайна. Подойдёт, когда стандартный шаблонный UI не устраивает. 1 025 790установок design-taste-frontend Leonxlnx Скилл задаёт арт-дирекцию для публичных страниц и рабочих экранов, а затем проверяет результат в браузере по скриншотам. Нужен, когда интерфейс выглядит шаблонным или недоработанным. CX Codex +1 678 700установок prototype Matt Pocock Создаёт временный прототип, чтобы проверить логику, модель состояния или вид интерфейса до работы над основным кодом. 986 201установок hyperframes heygen-com Скилл задаёт агенту правила рендера HTML-кода в видео через HyperFrames. Помогает собирать проморолики, эксплейнеры и титры прямо в коде проекта. CX Codex +1 1 200 000установок hyperframes-cli heygen-com Управляет проектами HyperFrames через терминал: собирает таймлайн, проверяет контраст кадров, запускает предпросмотр и рендерит видео локально или в облаке. CX Codex +1 1 300 000установок webapp-testing официальный anthropics Скилл запускает проверки локальных веб-приложений через Playwright: помогает отлаживать UI, делать скриншоты и смотреть логи браузера. 186 758установок

Из того же набора8

inertia-rails-architecture Задаёт серверные шаблоны для Rails + Inertia.js + React и разводит по нужным скиллам, когда вы строите страницу, форму или CRUD. CX Codex +1 537установок inertia-rails-pages Скилл для работы со страницами Inertia Rails: постоянные лейауты, навигация через Link и router, состояние из URL, отложенная загрузка и бесконечный скролл. CX Codex +1 504установок inertia-rails-controllers Подсказывает агенту, как правильно отдавать данные из Rails-контроллеров в Inertia.js: render inertia, типы пропсов, общие данные, flash и ошибки валидации. CX Codex +1 491установок inertia-rails-forms Скилл для работы с формами Inertia.js + Rails: создание, редактирование, удаление, визарды и загрузка файлов. Пригодится, когда нужно связать форму с контроллером Rails. CX Codex +1 486установок inertia-rails-testing Скилл для тестов Inertia Rails на RSpec и Minitest: проверка компонента, пропсов и flash без ручного разбора JSON. CX Codex +1 465установок shadcn-inertia Адаптирует компоненты shadcn/ui для связки Inertia.js, Ruby on Rails и React вместо Next.js. Помогает переписать формы и диалоги без react-hook-form. CX Codex +1 432установок inertia-rails-setup Скилл анализирует стек Inertia Rails в проекте, подбирает недостающие библиотеки и генерирует блок конфигурации в CLAUDE.md. Помогает при первом старте или смене инструментов. CX Codex +1 419установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой