Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Important
Security Advisory: React2Shell & two new vulnerabilities
Find out more

TypeScript

Last updated October 17, 2025

Next.js comes with built-in TypeScript, automatically installing the necessary packages and configuring the proper settings when you create a new project withcreate-next-app.

To add TypeScript to an existing project, rename a file to.ts /.tsx. Runnext dev andnext build to automatically install the necessary dependencies and add atsconfig.json file with the recommended config options.

Good to know: If you already have ajsconfig.json file, copy thepaths compiler option from the oldjsconfig.json into the newtsconfig.json file, and delete the oldjsconfig.json file.

IDE Plugin

Next.js includes a custom TypeScript plugin and type checker, which VSCode and other code editors can use for advanced type-checking and auto-completion.

You can enable the plugin in VS Code by:

  1. Opening the command palette (Ctrl/⌘ +Shift +P)
  2. Searching for "TypeScript: Select TypeScript Version"
  3. Selecting "Use Workspace Version"
TypeScript Command PaletteTypeScript Command Palette

Now, when editing files, the custom plugin will be enabled. When runningnext build, the custom type checker will be used.

The TypeScript plugin can help with:

  • Warning if invalid values forsegment config options are passed.
  • Showing available options and in-context documentation.
  • Ensuring the'use client' directive is used correctly.
  • Ensuring client hooks (likeuseState) are only used in Client Components.

🎥 Watch: Learn about the built-in TypeScript plugin →YouTube (3 minutes)

End-to-End Type Safety

The Next.js App Router hasenhanced type safety. This includes:

  1. No serialization of data between fetching function and page: You canfetch directly in components, layouts, and pages on the server. This datadoes not need to be serialized (converted to a string) to be passed to the client side for consumption in React. Instead, sinceapp uses Server Components by default, we can use values likeDate,Map,Set, and more without any extra steps. Previously, you needed to manually type the boundary between server and client with Next.js-specific types.
  2. Streamlined data flow between components: With the removal of_app in favor of root layouts, it is now easier to visualize the data flow between components and pages. Previously, data flowing between individualpages and_app were difficult to type and could introduce confusing bugs. Withcolocated data fetching in the App Router, this is no longer an issue.

Data Fetching in Next.js now provides as close to end-to-end type safety as possible without being prescriptive about your database or content provider selection.

We're able to type the response data as you would expect with normal TypeScript. For example:

app/page.tsx
asyncfunctiongetData() {constres=awaitfetch('https://api.example.com/...')// The return value is *not* serialized// You can return Date, Map, Set, etc.returnres.json()}exportdefaultasyncfunctionPage() {constname=awaitgetData()return'...'}

Forcomplete end-to-end type safety, this also requires your database or content provider to support TypeScript. This could be through using anORM or type-safe query builder.

Route-Aware Type Helpers

Next.js generates global helpers for App Router route types. These are available without imports and are generated duringnext dev,next build, or vianext typegen:

next-env.d.ts

Next.js generates anext-env.d.ts file in your project root. This file references Next.js type definitions, allowing TypeScript to recognize non-code imports (images, stylesheets, etc.) and Next.js-specific types.

Runningnext dev,next build, ornext typegen regenerates this file.

Good to know:

  • We recommend addingnext-env.d.ts to your.gitignore file.
  • The file must be in yourtsconfig.jsoninclude array (create-next-app does this automatically).

Examples

Type Checking Next.js Configuration Files

You can use TypeScript and import types in your Next.js configuration by usingnext.config.ts.

next.config.ts
importtype { NextConfig }from'next'constnextConfig:NextConfig= {/* config options here */}exportdefault nextConfig

Module resolution innext.config.ts is currently limited to CommonJS. However, ECMAScript Modules (ESM) syntax is available whenusing Node.js native TypeScript resolver for Node.js v22.10.0 and higher.

When using thenext.config.js file, you can add some type checking in your IDE using JSDoc as below:

next.config.js
// @ts-check/**@type{import('next').NextConfig} */constnextConfig= {/* config options here */}module.exports= nextConfig

Using Node.js Native TypeScript Resolver fornext.config.ts

Note: Available on Node.js v22.10.0+ and only when the feature is enabled. Next.js does not enable it.

Next.js detects theNode.js native TypeScript resolver viaprocess.features.typescript, added inv22.10.0. When present,next.config.ts can use native ESM, including top‑levelawait and dynamicimport(). This mechanism inherits the capabilities and limitations of Node's resolver.

In Node.js versionsv22.18.0+,process.features.typescript is enabled by default. For versions betweenv22.10.0 and22.17.x, opt in withNODE_OPTIONS=--experimental-transform-types:

Terminal
NODE_OPTIONS=--experimental-transform-typesnext<command>

For CommonJS Projects (Default)

Althoughnext.config.ts supports native ESM syntax in CommonJS projects, Node.js will still assumenext.config.ts is a CommonJS file by default, resulting in Node.js reparsing the file as ESM when module syntax is detected. Therefore, we recommend using thenext.config.mts file for CommonJS projects to explicitly indicate it's an ESM module:

next.config.mts
importtype { NextConfig }from'next'// Top-level await and dynamic import are supportedconstflags=awaitimport('./flags.js').then((m)=>m.default?? m)constnextConfig:NextConfig= {/* config options here */  typedRoutes:Boolean(flags?.typedRoutes),}exportdefault nextConfig

For ESM Projects

When"type" is set to"module" inpackage.json, your project uses ESM. Learn more about this settingin the Node.js docs. In this case, you can writenext.config.ts directly with ESM syntax.

Good to know: When using"type": "module" in yourpackage.json, all.js and.ts files in your project are treated as ESM modules by default. You may need to rename files with CommonJS syntax to.cjs or.cts extensions if needed.

Statically Typed Links

Next.js can statically type links to prevent typos and other errors when usingnext/link, improving type safety when navigating between pages.

Works in both the Pages and App Router for thehref prop innext/link. In the App Router, it also typesnext/navigation methods likepush,replace, andprefetch. It does not typenext/router methods in Pages Router.

Literalhref strings are validated, while non-literalhrefs may require a cast withas Route.

To opt-into this feature,typedRoutes needs to be enabled and the project needs to be using TypeScript.

next.config.ts
importtype { NextConfig }from'next'constnextConfig:NextConfig= {  typedRoutes:true,}exportdefault nextConfig

Next.js will generate a link definition in.next/types that contains information about all existing routes in your application, which TypeScript can then use to provide feedback in your editor about invalid links.

Good to know: If you set up your project withoutcreate-next-app, ensure the generated Next.js types are included by adding.next/types/**/*.ts to theinclude array in yourtsconfig.json:

tsconfig.json
{"include": ["next-env.d.ts",".next/types/**/*.ts","**/*.ts","**/*.tsx"  ],"exclude": ["node_modules"]}

Currently, support includes any string literal, including dynamic segments. For non-literal strings, you need to manually cast withas Route. The example below shows bothnext/link andnext/navigation usage:

app/example-client.tsx
'use client'importtype { Route }from'next'import Linkfrom'next/link'import { useRouter }from'next/navigation'exportdefaultfunctionExample() {constrouter=useRouter()constslug='nextjs'return (    <>      {/* Link: literal and dynamic */}      <Linkhref="/about" />      <Linkhref={`/blog/${slug}`} />      <Linkhref={('/blog/'+ slug)asRoute} />      {/* TypeScript error if href is not a valid route */}      <Linkhref="/aboot" />      {/* Router: literal and dynamic strings are validated */}      <buttononClick={()=>router.push('/about')}>Push About</button>      <buttononClick={()=>router.replace(`/blog/${slug}`)}>        Replace Blog      </button>      <buttononClick={()=>router.prefetch('/contact')}>        Prefetch Contact      </button>      {/* For non-literal strings, cast to Route */}      <buttononClick={()=>router.push(('/blog/'+ slug)asRoute)}>        Push Non-literal Blog      </button>    </>  )}

The same applies for redirecting routes defined by proxy:

proxy.ts
import { NextRequest, NextResponse }from'next/server'exportfunctionproxy(request:NextRequest) {if (request.nextUrl.pathname==='/proxy-redirect') {returnNextResponse.redirect(newURL('/',request.url))  }returnNextResponse.next()}
app/some/page.tsx
importtype { Route }from'next'exportdefaultfunctionPage() {return <Linkhref={'/proxy-redirect'asRoute}>Link Text</Link>}

To accepthref in a custom component wrappingnext/link, use a generic:

importtype { Route }from'next'import Linkfrom'next/link'functionCard<Textendsstring>({ href }: { href:Route<T>|URL }) {return (    <Linkhref={href}>      <div>My Card</div>    </Link>  )}

You can also type a simple data structure and iterate to render links:

components/nav-items.ts
importtype { Route }from'next'typeNavItem<Textendsstring=string>= {  href:T  label:string}exportconstnavItems:NavItem<Route>[]= [  { href:'/', label:'Home' },  { href:'/about', label:'About' },  { href:'/blog', label:'Blog' },]

Then, map over the items to renderLinks:

components/nav.tsx
import Linkfrom'next/link'import { navItems }from'./nav-items'exportfunctionNav() {return (    <nav>      {navItems.map((item)=> (        <Linkkey={item.href}href={item.href}>          {item.label}        </Link>      ))}    </nav>  )}

How does it work?

When runningnext dev ornext build, Next.js generates a hidden.d.ts file inside.next that contains information about all existing routes in your application (all valid routes as thehref type ofLink). This.d.ts file is included intsconfig.json and the TypeScript compiler will check that.d.ts and provide feedback in your editor about invalid links.

Type IntelliSense for Environment Variables

During development, Next.js generates a.d.ts file in.next/types that contains information about the loaded environment variables for your editor's IntelliSense. If the same environment variable key is defined in multiple files, it is deduplicated according to theEnvironment Variable Load Order.

To opt-into this feature,experimental.typedEnv needs to be enabled and the project needs to be using TypeScript.

next.config.ts
importtype { NextConfig }from'next'constnextConfig:NextConfig= {  experimental: {    typedEnv:true,  },}exportdefault nextConfig

Good to know: Types are generated based on the environment variables loaded at development runtime, which excludes variables from.env.production* files by default. To include production-specific variables, runnext dev withNODE_ENV=production.

With Async Server Components

To use anasync Server Component with TypeScript, ensure you are using TypeScript5.1.3 or higher and@types/react18.2.8 or higher.

If you are using an older version of TypeScript, you may see a'Promise<Element>' is not a valid JSX element type error. Updating to the latest version of TypeScript and@types/react should resolve this issue.

Incremental type checking

Sincev10.2.1 Next.js supportsincremental type checking when enabled in yourtsconfig.json, this can help speed up type checking in larger applications.

Customtsconfig path

In some cases, you might want to use a different TypeScript configuration for builds or tooling. To do that, settypescript.tsconfigPath innext.config.ts to point Next.js to anothertsconfig file.

next.config.ts
importtype { NextConfig }from'next'constnextConfig:NextConfig= {  typescript: {    tsconfigPath:'tsconfig.build.json',  },}exportdefault nextConfig

For example, switch to a different config for production builds:

next.config.ts
importtype { NextConfig }from'next'constisProd=process.env.NODE_ENV==='production'constnextConfig:NextConfig= {  typescript: {    tsconfigPath: isProd?'tsconfig.build.json':'tsconfig.json',  },}exportdefault nextConfig
Why you might use a separatetsconfig for builds

You might need to relax checks in scenarios like monorepos, where the build also validates shared dependencies that don't match your project's standards, or when loosening checks in CI to continue delivering while migrating locally to stricter TypeScript settings (and still wanting your IDE to highlight misuse).

For example, if your project usesuseUnknownInCatchVariables but some monorepo dependencies still assumeany:

tsconfig.build.json
{"extends":"./tsconfig.json","compilerOptions": {"useUnknownInCatchVariables":false  }}

This keeps your editor strict viatsconfig.json while allowing the production build to use relaxed settings.

Good to know:

  • IDEs typically readtsconfig.json for diagnostics and IntelliSense, so you can still see IDE warnings while production builds use the alternate config. Mirror critical options if you want parity in the editor.
  • In development, onlytsconfig.json is watched for changes. If you edit a different file name viatypescript.tsconfigPath, restart the dev server to apply changes.
  • The configured file is used innext dev,next build, andnext typegen.

Disabling TypeScript errors in production

Next.js fails yourproduction build (next build) when TypeScript errors are present in your project.

If you'd like Next.js to dangerously produce production code even when your application has errors, you can disable the built-in type checking step.

If disabled, be sure you are running type checks as part of your build or deploy process, otherwise this can be very dangerous.

Opennext.config.ts and enable theignoreBuildErrors option in thetypescript config:

next.config.ts
importtype { NextConfig }from'next'constnextConfig:NextConfig= {  typescript: {// !! WARN !!// Dangerously allow production builds to successfully complete even if// your project has type errors.// !! WARN !!    ignoreBuildErrors:true,  },}exportdefault nextConfig

Good to know: You can runtsc --noEmit to check for TypeScript errors yourself before building. This is useful for CI/CD pipelines where you'd like to check for TypeScript errors before deploying.

Custom type declarations

When you need to declare custom types, you might be tempted to modifynext-env.d.ts. However, this file is automatically generated, so any changes you make will be overwritten. Instead, you should create a new file, let's call itnew-types.d.ts, and reference it in yourtsconfig.json:

tsconfig.json
{"compilerOptions": {"skipLibCheck":true//...truncated...  },"include": ["new-types.d.ts","next-env.d.ts",".next/types/**/*.ts","**/*.ts","**/*.tsx"  ],"exclude": ["node_modules"]}

Version Changes

VersionChanges
v15.0.0next.config.ts support added for TypeScript projects.
v13.2.0Statically typed links are available in beta.
v12.0.0SWC is now used by default to compile TypeScript and TSX for faster builds.
v10.2.1Incremental type checking support added when enabled in yourtsconfig.json.

Was this helpful?

supported.

[8]ページ先頭

©2009-2025 Movatter.jp