You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js表单action绑定Server Action触发TypeScript类型错误

解决Next.js中Form Action与Server Action类型不匹配问题

在Next.js项目里,客户端组件/components/button.tsx的DeleteButton组件中,将服务端组件/lib/actions.ts的deleteImage函数通过bind绑定id后赋值给form的action属性时,触发TypeScript类型错误。核心原因是deleteImage返回的Promise<{ message: string; } | undefined>与form action要求的void | Promise<void>类型不兼容。

相关客户端组件代码

export const DeleteButton = ({ id }: { id: string }) => {
  const deleteImageWithId = deleteImage.bind(null, id);
  return (
    <form
      action={deleteImageWithId}
      className="py-3 text-sm bg-gray-50 rounded-br-md w-full hover:bg-gray-100 text-center"
    >
      <DeleteBtn />
    </form>
  );
};

相关服务端组件代码

// Delete Image
export const deleteImage = async (id: string) => {
  const data = await getImageById(id);
  if (!data) return { message: "No data found" };

  await del(data.image);
  try {
    await prisma.upload.delete({
      where: { id },
    });
  } catch (error) {
    return { message: "Failed to delete data" };
  }

  revalidatePath("/");
};

完整错误信息

./components/button.tsx:44:7 Type error:
  Type '() => Promise<{ message: string; } | undefined>' is not assignable to type 'string | ((formData: FormData) => void | Promise<void>) | undefined'.
  Type '() => Promise<{ message: string; } | undefined>' is not assignable to type '(formData: FormData) => void | Promise<void>'.
  Type 'Promise<{ message: string; } | undefined>' is not assignable to type 'void | Promise<void>'.
  Type 'Promise<{ message: string; } | undefined>' is not assignable to type 'void | Promise<void>'.
  Type 'Promise<{ message: string; } | undefined>' is not assignable to type 'Promise<void>'.
  Type '{ message: string; } | undefined' is not assignable to type 'void'.
  Type '{ message: string; }' is not assignable to type 'void'.

解决方案

方案1:修改Server Action的返回逻辑,适配类型要求

Next.js的Form Action不期望函数返回自定义对象,而是推荐通过抛出错误或结合useFormState处理错误信息。调整deleteImage函数:

// Delete Image
export const deleteImage = async (id: string) => {
  const data = await getImageById(id);
  if (!data) {
    throw new Error("No data found");
  }

  await del(data.image);
  try {
    await prisma.upload.delete({
      where: { id },
    });
  } catch (error) {
    throw new Error("Failed to delete data");
  }

  revalidatePath("/");
};

之后前端可以用useFormState捕获错误并展示,同时函数返回Promise<void>(抛出错误时会被捕获,不影响类型),完全符合Form Action的要求。

方案2:在客户端包装适配类型的函数

如果不想修改原有Server Action,可以在客户端组件中包装一个忽略返回值的函数:

export const DeleteButton = ({ id }: { id: string }) => {
  // 包装函数,适配Form Action的类型签名
  const handleDelete = async (_formData: FormData) => {
    await deleteImage(id);
  };

  return (
    <form
      action={handleDelete}
      className="py-3 text-sm bg-gray-50 rounded-br-md w-full hover:bg-gray-100 text-center"
    >
      <DeleteBtn />
    </form>
  );
};

这里handleDelete明确接受FormData参数(即使不用),并返回Promise<void>,完美匹配Form Action的类型要求,同时保留原有业务逻辑。

内容的提问来源于stack exchange,提问作者eko pram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:28:16