Next.js 13执行npx run build时触发Type Error错误求助
解决Next.js构建时客户端组件Props类型错误
错误信息
Type error: Type 'OmitWithTag<{ user: User; cupons: Cupon[]; }, keyof LayoutProps, "default">' does not satisfy the constraint '{ [x: string]: never; }'. Property 'user' is incompatible with index signature. Type 'User' is not assignable to type 'never'. 24 | 25 | // Check the prop type of the entry function > 26 | checkFields<Diff<LayoutProps, FirstArg<TEntry['default']>, 'default'>>() | ^ 27 | 28 | // Check the arguments and return type of the generateMetadata function 29 | if ('generateMetadata' in entry) {
相关代码
components/layout.tsx
"use client"; import React from "react"; import Container from "@/components/ui/container"; import NextImage from "next/image"; import moment from "moment"; import { User, Cupon } from "@/types"; const Layout = ({ user, cupons }: { user: User; cupons: Cupon[] }) => { const userCoupons = user.cupons .map((userCupon: any) => { return cupons.find((cupon: any) => cupon.id === userCupon.cuponId); }) .filter(Boolean); return ( <Container> <div className="flex flex-col mt-20 p-3 space-y-3"> <h1 className="text-3xl font-bold text-left">User Page</h1> <div className="flex items-start justify-start gap-7"> <NextImage alt="user_img" src={user.image} width={400} height={400} className="rounded-md" /> <div className="flex flex-col items-start justify-start pt-3"> <h1 className="text-2xl font-semibold text-left"> Personal Information </h1> <hr className="w-full text-black" /> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75 mt-3"> Name: {user.name} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75 mt-3"> Username: {`@${user.name.split(" ").join("_").toLowerCase()}`} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> Email: {user.email} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> Cupons Claimed: {user.cupons.length} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> User Since: {moment(user.createdAt).format("DD/MM/YYYY")} </h1> <br /> <br /> <h1 className="text-2xl font-semibold text-left"> Accoutnt Security </h1> <hr className="w-full text-black" /> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75 mt-3"> Auth provider: {user.accounts[0].provider} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> User ID: {user.accounts[0].id} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> Auth type: {user.accounts[0].type} </h1> </div> <div className="flex flex-col items-start justify-start pt-3"> <h1 className="text-2xl font-semibold text-left">Cupons Claimed</h1> <hr className="w-full text-black" /> {userCoupons.map((cupon: any) => ( <div key={cupon.id} className="flex items-start justify-start mt-3 bg-gray-300 bg-opacity-40 p-3 rounded-md w-full" > <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> Cupon ID: {cupon.id} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> Cupon Code: {cupon.code} </h1> <h1 className="text-[17px] font-semibold text-left text-slate-900 opacity-75"> Cupon Value: {cupon.value} </h1> </div> ))} </div> </div> </div> </Container> ); }; export default Layout;
app/[storeId]/[userId]/page.tsx
import React from "react"; import Layout from "../components/layout"; import getCupons from "@/actions/get-cupons"; interface UserPageProps { params: { userId: string; storeId: string; }; } const UserPage: React.FC<UserPageProps> = async ({ params }) => { const user = (await getUser(params.userId)) as any; const cupons = (await getCupons(params.storeId)) as any; const { userData } = JSON.parse(user) as any; return ( <div> <Layout user={userData} cupons={cupons} /> </div> ); }; export default UserPage;
解决方案
1. 避免组件命名冲突
Next.js对App Router中的layout.tsx有特殊类型约定,即使组件在components目录,命名为Layout也可能触发内部类型检查混淆。将组件重命名为UserLayout:
- 修改
layout.tsx为user-layout.tsx,并更新组件定义:"use client"; import React from "react"; import Container from "@/components/ui/container"; import NextImage from "next/image"; import moment from "moment"; import { User, Cupon } from "@/types"; interface UserLayoutProps { user: User; cupons: Cupon[]; } const UserLayout = ({ user, cupons }: UserLayoutProps) => { // 原有逻辑保持不变 }; export default UserLayout; - 更新
page.tsx中的导入和使用:import React from "react"; import UserLayout from "../components/user-layout"; import getCupons from "@/actions/get-cupons"; import getUser from "@/actions/get-user"; interface UserPageProps { params: { userId: string; storeId: string; }; } const UserPage: React.FC<UserPageProps> = async ({ params }) => { const userRes = await getUser(params.userId); const { userData } = JSON.parse(userRes) as { userData: User }; const cupons = await getCupons(params.storeId) as Cupon[]; return ( <div> <UserLayout user={userData} cupons={cupons} /> </div> ); }; export default UserPage;
2. 严格匹配Props类型,移除宽泛断言
去掉代码中as any的宽泛断言,明确指定类型,确保传递给客户端组件的Props与组件定义完全一致:
- 确保
getUser返回结果解析为{ userData: User }结构 - 确保
getCupons返回类型为Cupon[]
3. 检查基础类型定义
确认@/types中的User和Cupon类型无循环引用或不可序列化字段(如函数、Symbol):
// @/types/index.ts export interface User { id: string; name: string; email: string; image: string; createdAt: string; cupons: { cuponId: string }[]; accounts: { provider: string; id: string; type: string; }[]; } export interface Cupon { id: string; code: string; value: string | number; }
4. 升级Next.js版本
若以上方法无效,尝试升级Next.js到最新稳定版,该错误可能是旧版本的类型检查bug导致。
内容的提问来源于stack exchange,提问作者Updater XD
相关产品推荐
相关产品推荐

