typescript - În Sveltekit, poți returna 2 ActionResults de tip fail?
Am o acțiune de formular în fișierul meu +page.server.ts și returnez un fail dacă eșuează validarea schema zod, ceea ce funcționează. Totuși, atunci când returnez un alt fail când PocketBase aruncă o eroare de email deja utilizat, primesc această eroare de tip pentru fiecare câmp în afară de 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[]; }'
Întrebări :
- Este posibil să trimiți mai mult de 1 eșec dintr-un fișier
+page.server.ts? - Cum pot să remediez corect aceste avertismente de tip?
- Fac asta corect, dacă nu, cum pot să repar?
+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, '/');
}
};
Răspuns #1
Poți returna doar un singur rezultat de eșec.
Dacă păstrezi cele două rezultate de eșec, dar vrei să rezolvi problema TS, ai putea declara un tip și să afirmi că erorile verificării emailului se conformează acestuia. De exemplu.
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' };
Rețineți că as Errors nu va prinde proprietăți suplimentare. Deci, dacă scrieți greșit o proprietate, nu veți primi o eroare de compilare.
Tipul lui errors este derivat din toate valorile posibile returnate de funcție, așa că dacă mai întâi combini toate erorile într-un singur obiect și returnezi doar un singur rezultat de eșec, nepotrivirea de tip ar trebui deja să fie rezolvată prin combinare.
Dacă ar exista suport pentru validare asincronă în Zod, ai putea doar să faci validarea completă în acest mod. În prezent, probabil că ar trebui să o faci manual sau să folosești o bibliotecă pentru îmbinarea obiectelor.
