
Next.js 13+ App Router 要求 layout 组件的 default export 函数仅接收 children 参数,自定义 Props 类型若包含 params 或 searchParams 将触发类型校验失败;正确做法是分离参数声明:generateMetadata 可使用完整参数类型,而 layout 主函数仅声明 children。
next.js 13+ app router 要求 layout 组件的 `default export` 函数仅接收 `children` 参数,自定义 `props` 类型若包含 `params` 或 `searchparams` 将触发类型校验失败;正确做法是分离参数声明:`generatemetadata` 可使用完整参数类型,而 layout 主函数仅声明 `children`。
在 Next.js 的 App Router 中,layout.tsx 是一个特殊组件,其核心职责是包裹子路由内容(即 children)并提供共享 UI 结构与元数据。它并非页面级组件(如 page.tsx),因此 不支持直接通过函数参数解构 params 或 searchParams —— 这些动态路由参数仅对 page.tsx、route.ts 和 generateMetadata 等入口函数有效。
上述报错:
Layout "app/[prefName]/create/layout.tsx" has an invalid "default" export: Type "Props" is not valid.
根本原因在于:Next.js 内部类型检查器(见 checkFields
✅ 正确写法:参数职责分离
- generateMetadata 函数可自由使用含 params 和 searchParams 的完整类型(用于服务端解析路由上下文);
- default export 的 layout 函数只接收 children,其他逻辑应通过 useParams(客户端)或服务端预处理(如 generateMetadata 中提前读取)实现。
以下是修复后的标准实践:
// app/[prefName]/create/layout.tsx
import type { Metadata } from "next";
import { lookupPrefecture } from "@/config/prefectures";
// ✅ generateMetadata 可使用完整参数类型
type GenerateMetadataProps = {
params: { prefName: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export async function generateMetadata(
{ params, searchParams }: GenerateMetadataProps,
): Promise<Metadata> {
const { prefName } = params;
const encodedPrefName = decodeURIComponent(prefName);
const prefectureName = lookupPrefecture(encodedPrefName);
return {
title: `${prefectureName} | Create Post`,
openGraph: {
images: ["/some-specific-page-image.jpg"],
},
};
}
// ✅ layout 主函数仅声明 children —— 这是强制约定
export default function CreateLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}⚠️ 注意事项:
- 不要在 layout 默认导出函数中尝试解构 params 或 searchParams,即使使用 useParams() 也需注意:useParams 在 layout 中可能返回空对象(因 layout 渲染时机早于路由参数完全解析),应优先在 page.tsx 或 generateMetadata 中处理。
- 若需在 layout 中访问动态参数并执行服务端逻辑(如权限校验、数据预取),应使用 generateMetadata 的 parent 参数链式传递,或改用 page.tsx + Suspense + loading.tsx 组合。
- 所有自定义类型(如 Props)若仅用于 generateMetadata,请明确命名(如 GenerateMetadataProps),避免误导性复用到 layout 函数签名中。
总结:Next.js 的类型约束本质是设计契约的体现——layout 是静态布局容器,而非路由处理器。坚守 children-only 的默认导出签名,既符合框架语义,也能彻底规避此类类型错误。










