typescript - Trong Sveltekit, bạn có thể trả về 2 ActionResults thất bại không?
Tôi có một hành động form trong tệp +page.server.ts của mình và tôi đang trả về fail nếu nó không vượt qua xác thực schema zod, điều này đang hoạt động. Tuy nhiên, khi tôi trả về một fail khác khi PocketBase ném ra lỗi email đã được sử dụng, tôi nhận được lỗi kiểu cho mọi trường ngoại trừ email.
Typescript WarningProperty 'password' does not exist on type '{ password?: string[] | undefined; passwordConfirm?: string[] | undefined; email?: string[] | undefined; name?: string[] | undefined; terms?: string[] | undefined; } | { email: string[]; }'.
Property 'password' does not exist on type '{ email: string[]; }'
Câu hỏi:
- Có thể gửi hơn 1 lỗi từ một tệp
+page.server.tskhông? - Làm thế nào tôi có thể sửa đúng các cảnh báo kiểu này?
- Tôi có đang làm đúng cách không, nếu không thì làm thế nào để tôi có thể sửa?
+page.svelte...
<input id="password"
name="password"
type="password"
placeholder="Password"
class="input input-bordered w-full"
/>
<label class="label" for="password">
{#if form?.errors?.password}
<!--^^^Type Error Here-->
<span class="label-text-alt text-error">{form?.errors?.password[0]}</span>
<!--^^^Type Error Here-->
{/if}
</label>
...
//Type of errors coming from +page.server.ts into +page.svelte
(property) errors: {
password?: string[] | undefined;
passwordConfirm?: string[] | undefined;
email?: string[] | undefined;
name?: string[] | undefined;
terms?: string[] | undefined;
} | {
email: string[];
} | undefined
+page.server.tsexport const actions: Actions = {
default: async ({ locals, request }) => {
const formData = Object.fromEntries(await request.formData()) as {
email: string;
password: string;
passwordConfirm: string;
name: string;
terms: string;
};
const result = registerSchema.safeParse(formData);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { password, passwordConfirm, ...rest } = formData;
if (!result.success) {
const { fieldErrors: errors } = result.error.flatten();
const data = {
data: rest,
errors
};
return fail(400, data);
}
try {
await locals.pb.collection('users').create(formData);
await locals.pb.collection('users').authWithPassword(formData.email, formData.password);
} catch (e) {
if (e instanceof ClientResponseError) {
const data = {
data: rest,
errors: {
email: ['Email already exists']
}
};
return fail(400, data);
}
throw error(500, 'Something went wrong');
}
throw redirect(303, '/');
}
};
Câu trả lời #1
Bạn chỉ có thể trả về một kết quả thất bại.
Nếu bạn giữ lại hai kết quả thất bại, nhưng muốn sửa vấn đề TS, bạn có thể khai báo một kiểu và khẳng định rằng các lỗi của kiểm tra email tuân theo kiểu đó. Ví dụ.
const formData = Object.fromEntries(await request.formData()) as {
email: string;
password: string;
};
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
// This matches errors of Zob validation
type Errors = Partial<Record<keyof typeof formData, string[]>>;
const result = schema.safeParse(formData);
if (!result.success) {
return fail(400, {
errors: result.error.flatten().fieldErrors,
});
}
if (formData.email == '[email ') {
return fail(400, {
errors: {
email: ['already exists'],
} as Errors, // This ensures that the errors type is the same
});
}
return { message: 'ok' };
Lưu ý rằng as Errors sẽ không bắt các thuộc tính thừa. Vì vậy nếu bạn viết sai chính tả một thuộc tính, bạn sẽ không nhận được lỗi biên dịch.
Kiểu của errors được xác định từ tất cả các giá trị có thể trả về của hàm, vì vậy nếu bạn đầu tiên gộp tất cả các lỗi vào một đối tượng và chỉ trả về một kết quả thất bại, sự không khớp kiểu dữ liệu nên đã được xử lý thông qua việc gộp đó.
Nếu Zod có hỗ trợ xác thực bất đồng bộ, bạn có thể thực hiện xác thực đầy đủ theo cách đó. Hiện tại bạn có lẽ sẽ phải làm thủ công hoặc sử dụng một thư viện hợp nhất đối tượng.
