Skip to content

Docs · Framework

TypeScript

Strict mode, the @/ path alias and typed routes.

Everything is written in TypeScript 5.9 with strict mode on. Next.js compiles it; tsc only checks types.

Install

create-next-app sets TypeScript up. By hand, install it and run the dev server once: Next.js writes tsconfig.json and next-env.d.ts for you.

pnpm add -D typescript @types/node @types/react @types/react-dom

tsconfig.json

tsconfig.json
{  "compilerOptions": {    "target": "ES2017",    "lib": ["dom", "dom.iterable", "esnext"],    "allowJs": true,    "skipLibCheck": true,    "strict": true,    "noEmit": true,    "esModuleInterop": true,    "module": "esnext",    "moduleResolution": "bundler",    "resolveJsonModule": true,    "isolatedModules": true,    "jsx": "react-jsx",    "incremental": true,    "plugins": [      {        "name": "next"      }    ],    "paths": {      "@/*": ["./src/*"]    }  },  "include": [    "next-env.d.ts",    "**/*.ts",    "**/*.tsx",    ".next/types/**/*.ts",    ".next/dev/types/**/*.ts",    "**/*.mts"  ],  "exclude": ["node_modules"]}
  • strict catches missing null checks and implicit any.
  • paths maps @/ to src/, so imports read @/components/ui/button from anywhere.
  • The next plugin adds editor hints for Next.js files.

Typed routes

Next.js generates global types for every route. Use them for layouts, pages and route handlers instead of writing the params by hand:

Route types
// Generated by Next.js: no imports neededexport default function RootLayout({ children }: LayoutProps<"/">) { /* … */ } export default async function Page({ params }: PageProps<"/blog/[slug]">) {  const { slug } = await params;} export async function GET(_req: Request, { params }: RouteContext<"/source/[dir]/[file]">) {  const { dir, file } = await params;}

Component props

Components that wrap an HTML element take all of its props, so aria-*, name and event handlers just work:

text-field.tsx
import type { ComponentProps } from "react"; // Every <input> prop, minus "size", plus our ownexport type TextFieldProps = Omit<ComponentProps<"input">, "size"> & {  label: string;  error?: string | null;};

Check types

pnpm typecheck

This runs tsc --noEmit. next build checks types too, but running it alone is faster while you work.