Using nextjs15, when I call a server action from a form in a server component with a bind, I have the following error when I compile my project for production mode (in dev mode, it works):
Type error: Type '() => Promise<{ message: string; }>' is not assignable to type 'string | ((formData: FormData) => void | Promise<void>) | undefined'.
Type '() => Promise<{ message: string; }>' is not assignable to type '(formData: FormData) => void | Promise<void>'.
Type 'Promise<{ message: string; }>' is not assignable to type 'void | Promise<void>'.
Type 'Promise<{ message: string; }>' is not assignable to type 'Promise<void>'.
Type '{ message: string; }' is not assignable to type 'void'.
31 |
32 | return (
> 33 | <form action={deleteInvoiceWithId}>
| ^
34 | <button type="submit" className="rounded-md border p-2 hover:bg-gray-100">
35 | <span className="sr-only">Delete</span>
36 | <TrashIcon className="w-4" />
Static worker exited with code: 1 and signal: null
ELIFECYCLE Command failed with exit code 1.
The code :
export function DeleteInvoice({ id }: { id: string }) {
const deleteInvoiceWithId = deleteInvoice.bind(null, id);
return (
<form action={deleteInvoiceWithId}>
<button type="submit" className="rounded-md border p-2 hover:bg-gray-100">
<span className="sr-only">Delete</span>
<TrashIcon className="w-4" />
</button>
</form>
);
}
export async function deleteInvoice(id: string) {
try {
await sql`DELETE FROM invoices WHERE id = ${id}`;
revalidatePath('/dashboard/invoices');
return { message: 'Deleted Invoice.' };
} catch (error) {
return { message: 'Database Error: Failed to Delete Invoice.' };
}
}
Please note that this example comes from nextjs.org training course here
based on the error, the server action is returning something-- object of
Type '{ message: string; }'
though, next.js 15 form actions must return void or Promise as this is a server side execution rather. hence the rest of the error:
is not assignable to type '(formData: FormData) => void | Promise<void>'
remove return statement:
export async function deleteInvoice(id: string) {
try {
await sql`DELETE FROM invoices WHERE id = ${id}`;
revalidatePath('/dashboard/invoices');
} catch (error) {
console.error('Failed to delete invoice:', error);
throw new Error('Failed to delete invoice');
}
}