Next.js构建时传递数据库Diary对象的TypeScript类型错误解决
解决Next.js中传递Diary对象到组件的TypeScript类型错误
问题核心
错误根源在于Prisma查询结果的类型不匹配:db.diary.findFirst()返回的类型是Diary | null,但DiaryEditForm组件的props要求传入必填的Diary类型,同时未处理数据库查询不到对应日记的场景,直接传递可能为null的值会引发类型报错及潜在运行时错误。
代码问题定位
页面代码(问题点)
import { db } from "@/db"; import DiaryEditForm from "@/components/diary-edit-form"; interface DiaryEditPageProps { params: { id: string; }; } export default async function DiaryEditPage(props: DiaryEditPageProps) { const id = parseInt(props.params.id); const diary = await db.diary.findFirst({ where: { id }, }); // 此处diary可能为null,不符合组件的必填Diary类型要求 return ( <div> <DiaryEditForm diary={diary} /> </div> ); }
组件代码(依赖正确类型)
"use client"; import { Diary } from "@prisma/client"; import { useState } from "react"; import * as actions from "@/actions"; interface DiaryEditFormProps { diary: Diary; // 要求必填的Diary类型 } export default function DiaryEditForm({ diary }: DiaryEditFormProps) { const [content, setContent] = useState(diary); const handleEditorChange = (event: { target: { name: string; value: string }; }) => { const { name, value } = event.target; setContent((prevContent) => ({ ...prevContent, [name]: value, })); }; const editDiaryAction = actions.editDiary.bind( null, diary.id, content.title, content.description ); return ( <form action={editDiaryAction} className="space-y-4"> <h1 className="text-center font-semibold">Edit your Diary</h1> <div> <label htmlFor="title" className="block text-gray-700 font-medium mb-2 leading-tight" > Title </label> <input type="text" name="title" id="title" value={content.title} onChange={handleEditorChange} className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-gray-500" /> </div> <div> <label htmlFor="description" className="block text-gray-700 font-medium mb-2 leading-tight" > Description </label> <textarea name="description" id="description" value={content.description} onChange={handleEditorChange} className="min-h-32 w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-gray-500" ></textarea> </div> <button type="submit" className="bg-gray-600 text-white px-4 py-2 rounded" > Save </button> </form> ); }
解决方案
1. 处理查询结果的null情况(推荐)
在页面中检查查询结果,若未找到对应日记则返回404页面,同时确保传递给组件的diary是确定的Diary类型:
import { db } from "@/db"; import DiaryEditForm from "@/components/diary-edit-form"; import { notFound } from "next/navigation"; interface DiaryEditPageProps { params: { id: string; }; } export default async function DiaryEditPage(props: DiaryEditPageProps) { const id = parseInt(props.params.id); const diary = await db.diary.findFirst({ where: { id }, }); // 未找到日记时触发404 if (!diary) { notFound(); } // 此时diary类型已确定为Diary,可安全传递给组件 return ( <div> <DiaryEditForm diary={diary} /> </div> ); }
2. 优化组件事件处理类型(可选)
组件中handleEditorChange的事件类型可更精确,避免类型模糊问题:
const handleEditorChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { const { name, value } = event.target; // 断言name为Diary的属性键,避免类型报错 setContent((prevContent) => ({ ...prevContent, [name as keyof Diary]: value, })); };
额外提醒
不建议使用非空断言diary!强制类型转换,这种方式会隐藏潜在的null值风险,无法保证运行时的稳定性。
内容的提问来源于stack exchange,提问作者Abdullah Munshi
相关产品推荐
相关产品推荐

