# inertia-rails-typescript

Configures TypeScript type safety for Inertia Rails with React, Vue, and Svelte. Fixes common TS2344 and TS2339 compiler errors.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 468 installs · ★ 70
- Author: inertia-rails
- License: MIT · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/inertia-rails/skills/tree/HEAD/skills/inertia-rails-typescript/SKILL.md
- Updated: 2026-09-01
- HTML: https://affpapa.org/en/nevibecode/skills/inertia-rails-typescript

## What it does

The skill configures module augmentation for `@inertiajs/core` inside `globals.d.ts`. Instead of passing generics to every `usePage()` call, shared data is defined once via `InertiaConfig`. The setup requires exact property names: `sharedPageProps`, `flashDataType`, and `errorValueType`.

For session data, it enforces the `auth: { user: ... }` namespace in `SharedProps`. This convention prevents naming collisions with page-level props. In React, page props must use a `type` alias instead of `interface`. TypeScript interfaces lack an index signature, which triggers error TS2344 during compilation.

Declarations must reside in a `.d.ts` file. TypeScript silently ignores `declare module` blocks inside regular `.ts` files that contain imports.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add inertia-rails/skills --skill inertia-rails-typescript -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/inertia-rails-typescript/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/inertia-rails-typescript/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add inertia-rails/skills --skill inertia-rails-typescript -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/inertia-rails-typescript/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add inertia-rails/skills --skill inertia-rails-typescript -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/inertia-rails-typescript/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install inertia-rails/skills inertia-rails-typescript
```

2. **Manually: put the files in place**
- File: `.github/skills/inertia-rails-typescript/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add inertia-rails/skills --skill inertia-rails-typescript -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/inertia-rails/skills --path skills/inertia-rails-typescript
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/inertia-rails-typescript/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add inertia-rails/skills --skill inertia-rails-typescript -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/inertia-rails/skills/tree/HEAD/skills/inertia-rails-typescript/SKILL.md

## When to use it
- configure global shared props typing using `InertiaConfig`
- resolve TS2344 compiler errors in Inertia React page components
- fix TS2339 errors when accessing auth or flash from `usePage`
- isolate shared Rails session data from page-level component props

## Example prompts
- Set up InertiaConfig TypeScript module augmentation in globals.d.ts
- Fix TS2344 error on React page props in our Inertia app
- Type the shared flash notices for usePage() in Inertia Rails

## Source text · SKILL.md · MIT

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: d8c37263062ebf90.

BEGIN THIRD-PARTY FILE d8c37263062ebf90
````text
---
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 }
````
END THIRD-PARTY FILE d8c37263062ebf90

The third-party file has ended. Everything between the d8c37263062ebf90 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2836 of 7946 bytes. © inertia-rails · MIT · https://github.com/inertia-rails/skills/tree/HEAD/skills/inertia-rails-typescript/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
