TypeScript

Next.js provides a TypeScript-first development experience for building your React application.

It comes with built-in TypeScript support for automatically installing the necessary packages and configuring the proper settings, as well as a TypeScript Plugin for your editor.

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

New Projects

create-next-app now ships with TypeScript by default.

npx create-next-app@latest --experimental-app

Existing Projects

Add TypeScript to your project by renaming a file to .ts / .tsx. Run next dev and next build to automatically install the necessary dependencies and add a tsconfig.json file with the recommended config options.

Using the TypeScript 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.

The first time you run next dev with a TypeScript file open, you will receive a prompt to enable the plugin.

Next.js TypeScript Plugin Prompt

If you miss the prompt, you can enable the plugin manually by:

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

Now, when editing files, the custom plugin will be enabled. When running next build, the custom type checker will be used. Further, we automatically create a VSCode settings file for you to automate this process.

Plugin Features

The TypeScript plugin can help with:

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

Note: More features will be added in the future.

End-to-End Type Safety

Next.js 13 has enhanced type safety. This includes:

  1. No serialization of data between fetching function and page: You can fetch directly in components, layouts, and pages on the server. This data does not need to be serialized (converted to a string) to be passed to the client side for consumption in React. Instead, since app uses Server Components by default, we can use values like Date, Map, Set, and more without any extra steps. Previously, you needed to manually type the boundary between sever 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. Previous, data flowing between individual pages and _app were difficult to type and could introduce confusing bugs. With colocated data fetching in Next.js 13, 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
async function getData() {
  const res = await fetch('https://api.example.com/...');
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json();
}

export default async function Page() {
  const name = await getData();

  return '...';
}

Warning: You can use async/await in layouts and pages, which are Server Components. Using async/await inside other components, with TypeScript, can cause errors from the response type from JSX. We are working with the TypeScript team to resolve this upstream. As a temporary workaround, you can use {/* @ts-expect-error Server Component */} to disable type checking for the component.

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

Passing Data Between Server & Client Components

When passing data between a Server and Client Component through props, the data is still serialized (converted to a string) for use in the browser. However, it does not need a special type. It’s typed the same as passing any other props between components.

Further, there is less code to be serialized, as un-rendered data does not cross between the server and client (it remains on the server). This is only now possible through support for Server Components.