---
title: "TypeScript Plugin"
description: "The Next.js TypeScript language service plugin enhances the development experience within the app directory by providing rich intellisense, inline documentation, and semantic diagnostics for entry ..."
last_updated: "2026-09-23T10:52:03.144385+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/build-and-config/typescript-plugin"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/next/src/server/typescript/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/index.ts)
- [packages/next/src/server/typescript/rules/config.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/config.ts)
- [packages/next/src/server/typescript/rules/entry.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/entry.ts)
- [packages/next/src/server/lib/router-utils/typegen.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts)
- [packages/next/src/server/typescript/rules/client-boundary.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/client-boundary.ts)
- [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts)
- [packages/next/src/server/next-typescript.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-typescript.ts)
- [packages/next/src/server/typescript/rules/server-boundary.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server-boundary.ts)
- [packages/next/src/server/typescript/rules/metadata.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts)
- [packages/next/src/lib/typescript/diagnosticFormatter.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/diagnosticFormatter.ts)
- [packages/next/src/server/typescript/rules/server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/diagnosticFormatter.ts)
- [packages/next/src/cli/next-typegen.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-typegen.ts)
- [packages/next/src/server/typescript/utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/utils.ts)
- [packages/next/src/lib/verify-typescript-setup.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/verify-typescript-setup.ts)
- [packages/next/src/server/typescript/rules/error.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/error.ts)
- [packages/next/src/lib/load-custom-routes.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/load-custom-routes.ts)
- [packages/next/src/bundles/babel/packages/plugin-syntax-typescript.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/babel/packages/plugin-syntax-typescript.js)
- [packages/next/src/server/typescript/constant.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts)
- [packages/eslint-plugin-next/src/index.ts](https://github.com/blade47/next.js/blob/main/packages/eslint-plugin-next/src/index.ts)
- [packages/next/src/lib/typescript/runTypeCheck.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/runTypeCheck.ts)
- [packages/next/src/lib/typescript/writeConfigurationDefaults.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/writeConfigurationDefaults.ts)
- [packages/next/src/server/mcp/tools/get-compilation-issues.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/tools/get-compilation-issues.ts)
- [packages/next/src/bundles/babel/packages/preset-typescript.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/babel/packages/preset-typescript.js)
</details>

## Overview

The Next.js TypeScript language service plugin enhances the development experience within the `app` directory by providing rich intellisense, inline documentation, and semantic diagnostics for entry points, route segment configurations, and server/client component boundaries. Operating as a decorator over the standard TypeScript language service, the plugin intercepts completion requests, quick info lookups, and semantic checks to enforce framework conventions, validate exported configurations, and detect disallowed API usages at design time.

Sources: [packages/next/src/server/typescript/index.ts:1-33](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/index.ts#L1-L33)

## Language Service Plugin Architecture

### Overview

The Next.js TypeScript language service plugin initializes through a standard plugin module factory function that accepts the TypeScript module instance and constructs a decorated proxy over the host's `LanguageService`. Initialization extracts user options from `tsconfig.json`, sets up root directory matching for the `app` directory, and delegates autocompletion, quick info, and diagnostic requests to underlying rule handlers and AST utilities.

Sources: [packages/next/src/server/typescript/index.ts:31-57](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/index.ts#L31-L57), [packages/next/src/server/typescript/utils.ts:15-27](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/utils.ts#L15-L27)

### Plugin Initialization and LanguageService Proxying

When the TypeScript server loads Next.js, it invokes `createTSPlugin`, which returns a factory yielding the proxy object. If the plugin configuration explicitly sets `enabled` to `false`, the unmodified language service is returned immediately. Otherwise, `init` compiles a regular expression matching the project's app directory (`/src/app` or `/app`), and a null-prototype proxy object delegates every method of `tsModule.LanguageService` via runtime application.

```typescript
export const createTSPlugin: tsModule.server.PluginModuleFactory = ({
  typescript: ts,
}) => {
  function create(info: tsModule.server.PluginCreateInfo) {
    const isPluginEnabled = info.config.enabled ?? true

    if (!isPluginEnabled) {
      return info.languageService
    }

    init({
      ts,
      info,
    })

    const proxy: tsModule.LanguageService = Object.create(null)
    for (let k of Object.keys(info.languageService)) {
      const x = info.languageService[k as keyof tsModule.LanguageService]
      proxy[k] = (...args: Array<{}>) => x.apply(info.languageService, args)
    }
    // ...
```

Sources: [packages/next/src/server/typescript/index.ts:31-57](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/index.ts#L31-L57), [packages/next/src/server/typescript/utils.ts:15-27](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/utils.ts#L15-L27)

> [!WARNING]
> If `info.config.enabled` is explicitly set to `false`, the plugin bypasses initialization entirely and returns the raw host language service without attaching AST rule interceptors or diagnostics proxies.

Sources: [packages/next/src/server/typescript/index.ts:40-44](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/index.ts#L40-L44)

### Core AST Utility Integration

The plugin integrates tightly with TypeScript's compiler API through helper utilities in `utils.ts` and rule modules in `index.ts`. Key inspection functions check node positions, validate default function exports, parse file directives, and retrieve source files from the active program programmatically.

| Utility Function | Parameters | Return Type | Description |
| :--- | :--- | :--- | :--- |
| `init` | `opts: { ts, info }` | `void` | Computes project root and compiles `appDirRegExp`. |
| `getTypeChecker` | None | `tsModule.TypeChecker \| undefined` | Retrieves the type checker from the current language service program. |
| `getSource` | `fileName: string` | `tsModule.SourceFile \| undefined` | Fetches the AST source file for the given file path. |
| `isPositionInsideNode` | `position: number, node: tsModule.Node` | `boolean` | Checks if a caret position falls within a node's full start and width. |
| `isDefaultFunctionExport` | `node: tsModule.Node` | `boolean` | Determines if a node is an `export default function` declaration. |
| `isInsideApp` | `filePath: string` | `boolean` | Tests whether a file path resides inside the configured app directory. |
| `isAppEntryFile` | `filePath: string` | `boolean` | Validates that a file is a route `page` or `layout` inside the app directory. |
| `getEntryInfo` | `fileName: string, throwOnInvalidDirective?: boolean` | `{ client: boolean, server: boolean }` | Parses top-level `'use client'` or `'use server'` directives. |

Sources: [packages/next/src/server/typescript/utils.ts:15-181](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/utils.ts#L15-L181)

> [!NOTE]
> `getEntryInfo` inspects leading expression statements in the AST source file. If both `"use client"` and `"use server"` directives appear in the same file, or if a directive is placed below other statements when `throwOnInvalidDirective` is true, it throws a diagnostic descriptor object that is caught and reported by semantic diagnostics.

Sources: [packages/next/src/server/typescript/utils.ts:118-181](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/utils.ts#L118-L181)

### Diagnostic and Completion Interception Walkthrough

When the language service requests semantic diagnostics for a file via `proxy.getSemanticDiagnostics(fileName)`, the plugin executes a structured inspection pipeline:

1. `info.languageService.getSemanticDiagnostics(fileName)` retrieves existing compiler diagnostics.
2. `getSource(fileName)` loads the file's AST; if missing, prior diagnostics are returned unchanged.
3. `getEntryInfo(fileName, true)` determines client and server entry status, pushing a `MISPLACED_ENTRY_DIRECTIVE` error if directive ordering rules are violated.
4. `isInsideApp(fileName)` checks if the file is within the route segment boundaries, executing `errorEntry.getSemanticDiagnostics()` if applicable.
5. `ts.forEachChild(source, node => { ... })` iterates top-level AST nodes, branching on `ts.isImportDeclaration`, `ts.isVariableStatement`, `isDefaultFunctionExport`, and `ts.isFunctionDeclaration` to accumulate import restrictions, configuration exports, metadata rules, and server/client boundary checks.

Sources: [packages/next/src/server/typescript/index.ts:167-314](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/index.ts#L167-L314)

## Entry Point and Config Validation

### Overview

The TypeScript plugin validates Next.js file conventions across pages, layouts, and error boundary components. It inspects component parameter bindings against allowed property lists, resolves dynamic parallel route slot directories from disk, validates route segment configuration exports for static analyzability, and enforces client boundary requirements on error files.

Sources: [packages/next/src/server/typescript/rules/config.ts:1-694](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/config.ts#L1-L694), [packages/next/src/server/typescript/rules/entry.ts:1-164](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/entry.ts#L1-L164), [packages/next/src/server/typescript/rules/error.ts:1-37](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/error.ts#L1-L37)

### Page and Layout Prop Completions

The `entry` module provides IDE auto-completion and diagnostics for component parameter bindings in `page.js` and layout files. When a user requests completions inside a component parameter binding pattern, `getCompletionsAtPosition` evaluates whether the file is a page or layout entry.

For page entries, valid props are restricted to `params` and `searchParams`. For layout entries, the module scans the parent directory synchronously using `fs.readdirSync` with `withFileTypes: true` to discover parallel route slots (directories starting with `@`), stripping the `@` prefix and merging them into the allowed property list alongside `children`.

Sources: [packages/next/src/server/typescript/rules/entry.ts:1-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/entry.ts#L1-L140)

> [!NOTE]
> Parallel route slot discovery inspects the file system synchronously relative to `path.dirname(fileName)`. Any directory beginning with `@` contributes its slot name to the allowed layout props and type definitions.

Sources: [packages/next/src/server/typescript/rules/entry.ts:42-58](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/entry.ts#L42-L58)

### Route Segment Configuration Validation

The `config` module inspects exported variable statements to ensure that route segment configurations comply with allowed export identifiers and carry valid, statically analyzable values. 

| Config Option | Supported Types / Literals | Validation Rule / Behavior |
| :--- | :--- | :--- |
| `dynamic` | `"auto" \| "force-dynamic" \| "error" \| "force-static"` | Must match allowed string literal options. |
| `fetchCache` | `"force-no-store" \| "default-no-store" \| "default-cache" \| "force-cache"` | Validates static fetch caching behavior options. |
| `runtime` | `"nodejs" \| "edge" \| "experimental-edge"` | Enforces supported server runtime environments. |
| `maxDuration` | Numeric literal | Sets maximum execution time for the function. |
| `instant` | `true \| object \| false` | Enables instant navigation validation (type and hover support only). |
| `prefetch` | `"auto" \| "partial" \| "unstable_eager" \| "force-disabled" \| "allow-runtime"` | Controls client-side router prefetching behavior. |
| `unstable_dynamicStaleTime` | Number | Validates `Number(value.replace(/_/g, '')) >= 0`; pages only, forbidden in layouts. |

Sources: [packages/next/src/server/typescript/rules/config.ts:14-183](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/config.ts#L14-L183), [packages/next/src/server/typescript/rules/config.ts:577-690](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/config.ts#L577-L690)

The semantic diagnostic checker `getSemanticDiagnosticsForExportVariableStatement` verifies that configuration initializers are statically analyzable. If a configuration value is a BigInt, object literal, regular expression, or an arbitrary runtime expression that cannot be statically evaluated, it pushes an `INVALID_OPTION_VALUE` error code (`NEXT_TS_ERRORS.INVALID_OPTION_VALUE`).

Sources: [packages/next/src/server/typescript/rules/config.ts:577-690](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/config.ts#L577-L690)

> [!WARNING]
> Route segment configuration values must be statically analyzable literals. Dynamic expressions, runtime variables, and non-literal objects trigger an `INVALID_OPTION_VALUE` diagnostic.

Sources: [packages/next/src/server/typescript/rules/config.ts:658-672](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/config.ts#L658-L672)

### Error Boundary Client Directive Enforcement

The `errorEntry` module verifies that error boundary files (`error.tsx` or `global-error.tsx`) are marked as Client Components. When `getSemanticDiagnostics` runs on a source file matching `/[\\/]error\.tsx?$/` or `/[\\/]global-error\.tsx?$/`, it checks the `isClientEntry` boolean flag.

If `isClientEntry` evaluates to `false`, the plugin emits a diagnostic error across the entire file (`start: 0`, length: `source.text.length`) with code `NEXT_TS_ERRORS.INVALID_ERROR_COMPONENT`, requiring the addition of the `"use client"` directive.

Sources: [packages/next/src/server/typescript/rules/error.ts:7-33](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/error.ts#L7-L33)

## Server and Client Boundary Enforcement

### Overview

The TypeScript plugin enforces structural and serializability boundaries between Server and Client Components by inspecting files marked with `"use client"` and `"use server"` directives, and by filtering disallowed React APIs from Server Component compilation layers.

Sources: [packages/next/src/server/typescript/rules/client-boundary.ts:1-127](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/client-boundary.ts#L1-L127), [packages/next/src/server/typescript/rules/server-boundary.ts:1-159](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server-boundary.ts#L1-L159), [packages/next/src/server/typescript/rules/server.ts:1-92](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server.ts#L1-L92)

### Client Component Property Serializability Diagnostics

When analyzing component entry files containing the `"use client"` directive, `clientBoundary` validates that props passed across the network boundary are serializable. It inspects variable declarations and function export parameters via `getSemanticDiagnosticsForExportVariableStatement` and `getSemanticDiagnosticsForFunctionExport`.

Sources: [packages/next/src/server/typescript/rules/client-boundary.ts:7-124](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/client-boundary.ts#L7-L124)

If a component prop type resolves to a function type node, method signature, constructor type node, or class declaration, the plugin determines whether it represents an allowed server action or framework-injected error boundary callback.

Sources: [packages/next/src/server/typescript/rules/client-boundary.ts:51-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/client-boundary.ts#L51-L114)

| Check Condition | Target Property Names / AST Nodes | Action / Diagnostic Outcome |
| :--- | :--- | :--- |
| Server Action check | `propName === 'action' || /.+Action$/.test(propName)` | Allowed; functions matching action naming conventions are exempt from serialization errors. |
| Error Boundary check | `(isErrorFile || isGlobalErrorFile) && (propName === 'reset' || propName === 'retry')` | Allowed; framework-injected `reset` and `retry` functions in `error.tsx` or `global-error.tsx` are permitted. |
| Invalid function prop | Function type node or method signature without valid naming | Emits warning code `NEXT_TS_ERRORS.INVALID_CLIENT_ENTRY_PROP` (71007) requiring serialization. |
| Constructor / Class prop | Constructor type node or class declaration | Emits warning code `NEXT_TS_ERRORS.INVALID_CLIENT_ENTRY_PROP` (71007) for non-serializable class instances. |

Sources: [packages/next/src/server/typescript/rules/client-boundary.ts:75-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/client-boundary.ts#L75-L114), [packages/next/src/server/typescript/constant.ts:8-8](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L8-L8)

> [!WARNING]
> Component props in `"use client"` entry files must be serializable. Passing non-action functions, class instances, or constructors triggers a warning diagnostic (`INVALID_CLIENT_ENTRY_PROP`), unless the property is explicitly named as an action or handled as an error boundary retry callback.

Sources: [packages/next/src/server/typescript/rules/client-boundary.ts:68-100](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/client-boundary.ts#L68-L100)

### Server Action Return Type Enforcement

The `serverBoundary` module governs exports from files containing the `"use server"` directive. It inspects export declarations, variable statements, and function exports to ensure that all exported members evaluate to asynchronous functions returning a `Promise`.

Sources: [packages/next/src/server/typescript/rules/server-boundary.ts:55-157](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server-boundary.ts#L55-L157)

The execution walkthrough for checking server entry return types proceeds through the following helper functions:

1. `isFunctionReturningPromise()` retrieves the TypeScript type at the target node and queries its call signatures using `typeChecker.getSignaturesOfType()`.
2. For each signature, it obtains the return type via `signature.getReturnType()`. If the return type is a union type, it iterates over each constituent type; otherwise, it passes the single return type directly to `isPromiseType()`.
3. `isPromiseType()` casts the type to a `tsModule.TypeReference`, inspects its target reference, and matches its string representation against the pattern `/^Promise(<.+>)?$/` using `typeChecker.typeToString()`.
4. If any signature fails to return a `Promise`, `isFunctionReturningPromise` returns `false`, causing the plugin to emit an error diagnostic with code `NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN` (71011).

Sources: [packages/next/src/server/typescript/rules/server-boundary.ts:8-53](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server-boundary.ts#L8-L53), [packages/next/src/server/typescript/rules/server-boundary.ts:72-81](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server-boundary.ts#L72-L81), [packages/next/src/server/typescript/constant.ts:12-12](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L12-L12)

> [!NOTE]
> Non-async functions exported from `"use server"` files result in error code `INVALID_SERVER_ENTRY_RETURN`. The plugin requires every exported member to resolve to an asynchronous function signature returning a `Promise`.

Sources: [packages/next/src/server/typescript/rules/server-boundary.ts:144-153](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server-boundary.ts#L144-L153)

### Disallowed Server Component React APIs

The `serverLayer` module restricts stateful and DOM-dependent React APIs from being imported or used within Server Components. It evaluates completion entries, definition info nodes, and import declarations against explicit deny-lists defined in constants.

Sources: [packages/next/src/server/typescript/rules/server.ts:1-90](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server.ts#L1-L90), [packages/next/src/server/typescript/constant.ts:26-50](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L26-L50)

The disallowed React and React DOM APIs filtered on the server layer include:

- Disallowed React APIs (`DISALLOWED_SERVER_REACT_APIS`): `useState`, `useEffect`, `useEffectEvent`, `useLayoutEffect`, `useDeferredValue`, `useImperativeHandle`, `useInsertionEffect`, `useReducer`, `useRef`, `useSyncExternalStore`, `useTransition`, `Component`, `PureComponent`, `createContext`, `createFactory`, `experimental_useOptimistic`, `useOptimistic`, `useActionState`.
- Disallowed React DOM APIs (`DISALLOWED_SERVER_REACT_DOM_APIS`): `useFormStatus`, `useFormState`.

Sources: [packages/next/src/server/typescript/constant.ts:26-50](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L26-L50)

When `getSemanticDiagnosticsForImportDeclaration` encounters an import from `'react'` or `'react-dom'` containing any of these restricted identifiers in its named bindings, it generates an error diagnostic with code `NEXT_TS_ERRORS.INVALID_SERVER_API` (71001) stating that the API is not allowed in Server Components.

Sources: [packages/next/src/server/typescript/rules/server.ts:36-88](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/server.ts#L36-L88), [packages/next/src/server/typescript/constant.ts:2-2](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L2-L2)

## Metadata and Special Export Diagnostics

### Overview

The metadata rule engine validates static and dynamic metadata export type compliance across client and server boundaries. It intercepts variable statements, function declarations, and export declarations to ensure that Next.js special exports (`metadata`, `generateMetadata`, `viewport`, and `generateViewport`) conform to required typing and environment rules, emitting error or warning diagnostics via `NEXT_TS_ERRORS.INVALID_METADATA_EXPORT` (71008).

Sources: [packages/next/src/server/typescript/rules/metadata.ts:1-74](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L1-L74), [packages/next/src/server/typescript/rules/metadata.ts:75-242](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L75-L242), [packages/next/src/server/typescript/constant.ts:9-9](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L9-L9)

### Client-Side Boundary Enforcement

In client entry modules, exporting `metadata` or `generateMetadata` is prohibited. The `metadata.client` handler inspects both variable statements and function declarations, as well as named export clauses in export declarations, identifying forbidden names and generating error-category diagnostics.

Sources: [packages/next/src/server/typescript/rules/metadata.ts:6-74](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L6-L74)

> [!WARNING]
> Exporting `metadata` or `generateMetadata` from a Client Component file triggers error code `INVALID_METADATA_EXPORT` (71008) with message text stating that the API is not allowed in a Client Component.

Sources: [packages/next/src/server/typescript/rules/metadata.ts:15-68](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L15-L68), [packages/next/src/server/typescript/constant.ts:9-9](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L9-L9)

### Server-Side Type Compliance Walkthrough

For server components and layouts, the plugin checks whether `metadata` and `generateMetadata` exports possess explicit type annotations or correct return signatures. The type validation check proceeds through the following call sequence:

1. `getSemanticDiagnosticsForExportVariableStatement()` or `getSemanticDiagnosticsForExportDeclaration()` inspects the export node and extracts its underlying declaration.
2. `hasType(node)` evaluates the declaration: for function declarations, expressions, and arrow functions, it checks `node.type`. For variable declarations initialized with arrow functions or function expressions, it inspects `node.initializer.type`.
3. If `hasType()` returns `true`, type verification passes and no diagnostics are returned.
4. If missing an explicit type, the engine inspects modifier flags using `ts.SyntaxKind.AsyncKeyword` to determine if `generateMetadata` is asynchronous.
5. A warning diagnostic with code `NEXT_TS_ERRORS.INVALID_METADATA_EXPORT` is emitted, recommending `"Metadata"` for static exports and either `"Promise<Metadata>"` or `"Metadata"` depending on the async modifier for `generateMetadata`.

Sources: [packages/next/src/server/typescript/rules/metadata.ts:75-242](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L75-L242), [packages/next/src/server/typescript/rules/metadata.ts:244-282](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L244-L282)

### Metadata Diagnostic Reference

| Export Name | Node / Context | Diagnostic Category | Error Code | Message Text / Rule Condition |
| :--- | :--- | :--- | :--- | :--- |
| `metadata` / `generateMetadata` | Client Component (`client`) | Error | `71008` (`INVALID_METADATA_EXPORT`) | The Next.js API is not allowed in a Client Component. |
| `metadata` | Server Variable / Export (`server`) | Warning | `71008` (`INVALID_METADATA_EXPORT`) | The Next.js "metadata" export should be type of "Metadata" from "next". |
| `generateMetadata` | Server Function / Export (`server`) | Warning | `71008` (`INVALID_METADATA_EXPORT`) | The Next.js "generateMetadata" export should have a return type of "Metadata" or "Promise<Metadata>" from "next". |

Sources: [packages/next/src/server/typescript/rules/metadata.ts:1-242](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/rules/metadata.ts#L1-L242), [packages/next/src/server/typescript/constant.ts:9-9](https://github.com/blade47/next.js/blob/main/packages/next/src/server/typescript/constant.ts#L9-L9)

## Route and Link Type Generation

### Overview

Next.js generates typed route definitions, parameter maps, slot mappings, and validator artifacts via the `next-typegen` CLI utility, dev-server integration, and typegen modules. These files validate app pages, layouts, route handlers, and pages router endpoints, ensuring compile-time safety for typed navigation and form actions.

Sources: [packages/next/src/cli/next-typegen.ts:28-122](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-typegen.ts#L28-L122), [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts:1167-1202](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts#L1167-L1202), [packages/next/src/server/lib/router-utils/typegen.ts:430-669](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts#L430-L669)

### CLI Type Generation Execution Walkthrough

The `next-typegen` command coordinates project discovery, route analysis, and artifact generation through a specific operational sequence:

1. `getProjectDir(directory)` resolves the base project directory, verifying its existence on disk.
2. `loadConfig(PHASE_PRODUCTION_BUILD, baseDir)` loads the project configuration, after which `installBindings()` sets up SWC binaries.
3. `findPagesDir(baseDir)` locates the `app` and `pages` directories.
4. `verifyAndRunTypeScript(...)` checks TypeScript setup options, typed routes configuration, and strict route type flags.
5. `discoverRoutes(...)` scans the filesystem for `pageRoutes`, `pageApiRoutes`, `appRoutes`, `appRouteHandlers`, `layoutRoutes`, and `slots`.
6. `createRouteTypesManifest(...)` compiles route mappings, redirects, and rewrites into a structured route types manifest.
7. `writeRouteTypesManifest(...)` and `writeValidatorFile(...)` output `routes.d.ts` and `validator.ts` into the distribution types directory.
8. `writeCacheLifeTypes(...)` and `writeRootParamsTypes(...)` emit additional `cache-life.d.ts` and `root-params.d.ts` definitions.

Sources: [packages/next/src/cli/next-typegen.ts:32-121](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-typegen.ts#L32-L121)

### Validator File Generation and Route Configurations

`generateValidatorFile` processes sorted route paths to produce type checks for TypeScript modules. It filters out non-TypeScript files and non-page entries before constructing type assertion blocks using `__IsExpected<Specific extends ${typeWithRoute}>`.

Sources: [packages/next/src/server/lib/router-utils/typegen.ts:430-483](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts#L430-L483)

| Configuration Type | Route / Source Basis | Export Signature & Parameters | Validated File Types |
| :--- | :--- | :--- | :--- |
| `AppPageConfig` | `routesManifest.appPagePaths` | `default`: Component or function taking `{ params: PromisearamMap[Route]> }` | `.ts`, `.tsx` (page files) |
| `PagesPageConfig` | `routesManifest.pagesRouterPagePaths` | `default`: Component or function with data fetching (`getStaticProps`, `getServerSideProps`) | `.ts`, `.tsx` |
| `LayoutConfig` | `routesManifest.layoutPaths` | `default`: Component or function taking `LayoutProps<Route>` | `.ts`, `.tsx` |
| `RouteHandlerConfig` | `routesManifest.appRouteHandlers` | HTTP methods (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`) taking `NextRequest` and context | `.ts`, `.tsx` |
| `ApiRouteConfig` | `routesManifest.pageApiRoutes` | `default`: `(req: any, res: any) => ReturnType<NextApiHandler>` | `.ts`, `.tsx` |

Sources: [packages/next/src/server/lib/router-utils/typegen.ts:488-606](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts#L488-L606)

> [!CAUTION]
> Only TypeScript source files (`.ts` and `.tsx`) are included in validator file generation. JavaScript files are excluded because they exhibit too many type inference limitations for strict route verification.

Sources: [packages/next/src/server/lib/router-utils/typegen.ts:445-448](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts#L445-L448), [packages/next/src/server/lib/router-utils/typegen.ts:686-689](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts#L686-L689)

### Form Props and Typed Navigation Integration

The type generator defines form property types supporting typed navigation routes and server action functions. The `FormProps<RouteInferType>` type accepts an `action` property that can be a typed route implementation or a form data submission handler.

```typescript
type FormRestProps = Omit<OriginalFormProps, 'action'>

export type FormProps<RouteInferType> = {
  /**
   * `action` can be either a `string` or a function.
   * - If `action` is a string, it will be interpreted as a path or URL to navigate to when the form is submitted.
   *   The path will be prefetched when the form becomes visible.
   * - If `action` is a function, it will be called when the form is submitted. See the React docs for more.
   */
  action: __next_route_internal_types__.RouteImpl<RouteInferType> | ((formData: FormData) => void)
} & FormRestProps

export default function Form<RouteType>(props: FormProps<RouteType>): JSX.Element
```

Sources: [packages/next/src/server/lib/router-utils/typegen.ts:413-426](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts#L413-L426)

## TypeScript Environment Verification and Diagnostics

### Overview

Next.js verifies the TypeScript environment by checking package dependencies, validating and writing `tsconfig.json` default options, executing type checks against the program AST, and formatting diagnostics for user display.

Sources: [packages/next/src/lib/verify-typescript-setup.ts:56-84](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/verify-typescript-setup.ts#L56-L84)

### Dependency Verification and Native Compiler Handling

`verifyAndRunTypeScript` initiates verification by checking if TypeScript intent exists via `getTypeScriptIntent`, then validating required packages through `hasNecessaryDependencies`.

```typescript
const typescriptPackage: MissingDependency = {
  file: 'typescript/lib/typescript.js',
  pkg: 'typescript',
  exportsRestrict: true,
}

const requiredPackages: MissingDependency[] = [
  typescriptPackage,
  {
    file: '@types/react/index.d.ts',
    pkg: '@types/react',
    exportsRestrict: true,
  },
  {
    file: '@types/node/index.d.ts',
    pkg: '@types/node',
    exportsRestrict: true,
  },
]
```

Sources: [packages/next/src/lib/verify-typescript-setup.ts:22-40](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/verify-typescript-setup.ts#L22-L40), [packages/next/src/lib/verify-typescript-setup.ts:91-105](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/verify-typescript-setup.ts#L91-L105)

> [!NOTE]
> If `@typescript/native-preview` is detected in the project, Next.js can bypass missing standard `typescript` package errors for compilation while retaining `@types/react` and `@types/node` for type checking.

Sources: [packages/next/src/lib/verify-typescript-setup.ts:47-54](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/verify-typescript-setup.ts#L47-L54), [packages/next/src/lib/verify-typescript-setup.ts:110-124](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/verify-typescript-setup.ts#L110-L124)

### Configuration Defaults and Desired Compiler Options

`writeConfigurationDefaults` inspects the user's `tsconfig.json` and injects required or suggested compiler options based on the detected TypeScript version.

| Option Key | Setting Type | Target Value / Rule | Reason / Description |
| :--- | :--- | :--- | :--- |
| `target` | Suggested | `ES2017` | For top-level `await` support |
| `lib` | Suggested | `['dom', 'dom.iterable', 'esnext']` | Standard browser and ECMAScript globals |
| `allowJs` | Suggested | `true` | Permits JavaScript files in compilation |
| `skipLibCheck` | Suggested | `true` | Skips type checking of declaration files |
| `strict` | Suggested | `false` | Disables strict mode flags by default |
| `noEmit` | Suggested | `true` | Prevents emitting compiled output files |
| `incremental` | Suggested | `true` | Enables incremental compilation caching |
| `module` | Required | `esnext` | Required for dynamic `import()` support |
| `esModuleInterop` | Required | `true` | Requirement for SWC and Babel interop |
| `moduleResolution` | Required | `bundler` or `node` | Matches modern bundler or webpack resolution |
| `resolveJsonModule` | Required | `true` | Matches webpack module resolution |
| `isolatedModules` | Required | `true` | Requirement for SWC and Babel file-by-file transforms |
| `jsx` | Required | `react-jsx` | Next.js uses the React automatic runtime |

Sources: [packages/next/src/lib/typescript/writeConfigurationDefaults.ts:53-143](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/writeConfigurationDefaults.ts#L53-L143)

### Execution Walkthrough: Type Check and Diagnostic Formatting

When `shouldRunTypeCheck` is enabled, `runTypeCheck` executes the type checking pipeline through `typescript.createProgram` or `typescript.createIncrementalProgram`, emitting diagnostics and formatting errors via `getFormattedDiagnostic`.

1. `getTypeScriptConfiguration()` retrieves compiler options and file names from `tsConfigPath`.
2. `getDevTypesPath()` filters out stale `.next/dev/types` files during build mode.
3. `debugBuildPaths` filters app or pages paths if specified in build configuration.
4. `typescript.createProgram()` or `typescript.createIncrementalProgram()` instantiates the program AST with merged `getRequiredConfiguration()` options.
5. `program.emit()` and `typescript.getPreEmitDiagnostics()` collect all compile errors and warnings, filtering out test and mock files.
6. `getFormattedDiagnostic()` processes diagnostic codes (such as `2322`, `2344`, `2345`, `2559`, and `2820`) to produce contextual code frames and layout/page error descriptions.

Sources: [packages/next/src/lib/typescript/diagnosticFormatter.ts:1-52](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/diagnosticFormatter.ts#L1-L52), [packages/next/src/lib/typescript/diagnosticFormatter.ts:73-290](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/diagnosticFormatter.ts#L73-L290), [packages/next/src/lib/typescript/runTypeCheck.ts:39-149](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/runTypeCheck.ts#L39-L149), [packages/next/src/lib/typescript/runTypeCheck.ts:163-176](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/runTypeCheck.ts#L163-L176)

> [!WARNING]
> If a project's `tsconfig.json` extends another configuration file or includes `references`, automatic plugin and option injection is bypassed, and Next.js logs a recommendation to add the `{ name: 'next' }` plugin manually.

Sources: [packages/next/src/lib/typescript/writeConfigurationDefaults.ts:221-224](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/writeConfigurationDefaults.ts#L221-L224), [packages/next/src/lib/typescript/writeConfigurationDefaults.ts:345-359](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/typescript/writeConfigurationDefaults.ts#L345-L359)

## Related

- [Configuration Loading](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/build-and-config/configuration-loading)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/llms.txt) for all pages in this wiki.
