Skip to main content
Inertia provides first-class TypeScript support. You may configure global types using declaration merging, and pass generics to hooks and router methods for type-safe props, forms, and state management.

Using pnpm

Due to pnpm’s strict dependency isolation, @inertiajs/core is not accessible at node_modules/@inertiajs/core. Instead, it’s nested inside .pnpm/, which prevents TypeScript module augmentation from resolving the module. You may fix this by configuring pnpm to hoist the package. Add the following to your .npmrc file and run pnpm install.
public-hoist-pattern[]=@inertiajs/core
Alternatively, you may add @inertiajs/core as a direct dependency in your project.
pnpm add @inertiajs/core

Global Configuration

You may configure Inertia’s types globally by augmenting the InertiaConfig interface in the @inertiajs/core module. This is typically done in a global.d.ts file in your project’s root or types directory.
// global.d.ts
declare module "@inertiajs/core" {
  export interface InertiaConfig {
    sharedPageProps: {
      auth: { user: { id: number; name: string } | null };
      appName: string;
    };
    flashDataType: {
      toast?: { type: "success" | "error"; message: string };
    };
    errorValueType: string[];
  }
}
For module augmentation to work, your tsconfig.json needs to include .d.ts files. Make sure a pattern like "resources/js/**/*.d.ts" is present in the include array, adjusted to match your project’s directory structure.

Shared Page Props

The sharedPageProps option defines the type of data that is shared with every page in your application. With this configuration, page.props.auth and page.props.appName will be properly typed everywhere.
sharedPageProps: {
    auth: { user: { id: number; name: string } | null }
    appName: string
}

Flash Data

The flashDataType option defines the type of flash data in your application.
flashDataType: {
    toast?: { type: 'success' | 'error'; message: string }
}

Error Values

By default, validation error values are typed as string. You may configure TypeScript to expect arrays instead for multiple errors per field.
errorValueType: string[]
The next version of Laravel Wayfinder may automatically generate these types for you by analyzing your Laravel application. It generates TypeScript types for shared props, page props, form requests, and Eloquent models. This version is currently in beta.

Page Components

You may type the import.meta.glob result for better type safety when resolving page components.
import { createInertiaApp } from "@inertiajs/vue3";
import type { DefineComponent } from "vue";

createInertiaApp({
  resolve: (name) => {
    const pages = import.meta.glob<DefineComponent>("./Pages/**/*.vue", {
      eager: true,
    });
    return pages[`./Pages/${name}.vue`];
  },
  // ...
});

Page Props

You may type page-specific props by passing a generic to usePage(). These are merged with your global sharedPageProps, giving you autocomplete and type checking for both shared and page-specific data.
<script setup lang="ts">
import { usePage } from "@inertiajs/vue3";

const page = usePage<{
  posts: { id: number; title: string }[];
}>();
</script>

Form Helper

The form helper accepts a generic type parameter for type-safe form data and error handling. This provides autocomplete for form fields and errors, and prevents typos in field names.
<script setup lang="ts">
import { useForm } from "@inertiajs/vue3";

const form = useForm<{
  name: string;
  email: string;
  company: { name: string };
}>({
  name: "",
  email: "",
  company: { name: "" },
});
</script>

Nested Data and Arrays

Form types fully support nested objects and arrays. You may access and update nested fields using dot notation, and error keys are automatically typed to match.
import { useForm } from "@inertiajs/react";

const form = useForm<{
  user: { name: string; email: string };
  tags: { id: number; label: string }[];
}>({
  user: { name: "", email: "" },
  tags: [],
});

Remembering State

The useRemember hook accepts a generic type parameter for type-safe local state persistence, providing autocomplete and ensuring values match the expected types.
<script setup lang="ts">
import { useRemember } from "@inertiajs/vue3";

const filters = useRemember<{
  search: string;
  status: "active" | "inactive" | "all";
}>({
  search: "",
  status: "all",
});
</script>

Restoring State

The router.restore() method accepts a generic for typing state restored from history.
import { router } from "@inertiajs/react";

interface TableState {
  sortBy: string;
  sortDesc: boolean;
  page: number;
}

const restored = router.restore<TableState>("table-state");

if (restored) {
  console.log(restored.sortBy);
}

Router Requests

Router methods accept a generic for typing request data, providing type checking for the data being sent.
import { router } from "@inertiajs/react";

interface CreateUserData {
  name: string;
  email: string;
}

router.post<CreateUserData>("/users", {
  name: "John",
  email: "[email protected]",
});

Scoped Flash Data

The router.flash() method accepts a generic for typing page or section-specific flash data, separate from the global flashDataType configuration.
import { router } from "@inertiajs/react";

router.flash<{ paymentError: string }>({ paymentError: "Card declined" });

Client-Side Visits

The router.push() and router.replace() methods accept a generic for typing client-side visit props.
import { router } from "@inertiajs/react";

interface UserPageProps {
  user: { id: number; name: string };
}

router.push<UserPageProps>({
  component: "Users/Show",
  url: "/users/1",
  props: { user: { id: 1, name: "John" } },
});

router.replace<UserPageProps>({
  props: (current) => ({
    ...current,
    user: { ...current.user, name: "Updated" },
  }),
});