TypeScript in Next.js
.ts/.tsx file to a JavaScript project — or running create-next-app with the TypeScript option — is enough to get type checking, path alias resolution, and an auto-generated configuration wired up for you automatically.What Next.js sets up for you
next dev or next build in a project containing TypeScript files, Next.js detects that there's no tsconfig.json yet, creates one with sensible defaults, and installs the type packages it needs (typescript, @types/react, @types/node) if they're missing. It also generates a next-env.d.ts file.next-env.d.ts — auto-generated, do not edit
/// <reference types="next" /> /// <reference types="next/image-types/global" /> // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
next-env.d.ts is what makes Next.js's ambient types (like the shape of next/image) available across the project. It's committed to version control but regenerated automatically — never hand-edit it, and don't remove the reference comments inside it.Typing page props: params and searchParams
page.tsx receives params (the dynamic segment values matched by the URL) and searchParams (the parsed query string) as props. Typing them explicitly catches typos in dynamic segment names at compile time instead of at runtime.app/blog/[slug]/page.tsx
type PageProps = {
params: { slug: string }
searchParams: { [key: string]: string | string[] | undefined }
}
export default function BlogPostPage({ params, searchParams }: PageProps) {
const { slug } = params
const highlight = searchParams.highlight
return (
<article>
<h1>Post: {slug}</h1>
{highlight && <p>Highlighting: {highlight}</p>}
</article>
)
}params and searchParams are typed as Promise-wrapped values in Server Components, and must be awaited before use — a deliberate change to support streaming route parameters. If you're on Next.js 15+, type them as Promise<{ slug: string }> and await params at the top of the component. Always check the installed version's docs, since this is one of the more visible breaking changes between major versions.app/blog/[slug]/page.tsx — Next.js 15+ shape
type PageProps = {
params: Promise<{ slug: string }>
}
export default async function BlogPostPage({ params }: PageProps) {
const { slug } = await params
return <h1>Post: {slug}</h1>
}Why TypeScript pairs well with the App Router
App Router pattern | What TypeScript adds |
|---|---|
Server vs. Client Components | Catches accidental use of browser-only APIs in a Server Component at the type level (indirectly, via lint + editor tooling) |
| Guarantees the shape of dynamic segments matches what the route actually captures |
Server Actions | Types flow end-to-end from the form/client call through to the server function signature, with no manual API contract to keep in sync |
| Generic return types (e.g. |
Adding a
.ts/.tsxfile is enough to trigger automatic TypeScript setup — no manual installation required.next-env.d.tsis auto-generated and should never be edited by hand.Type
paramsandsearchParamsexplicitly on page components to catch mismatches at compile time.Next.js 15 changed
params/searchParamsto Promises in Server Components — check the docs for your installed version.TypeScript reinforces App Router conventions (Server/Client boundaries, Server Action signatures) that are otherwise only enforced at runtime.