typescript - V Sveltekite, môžete vrátiť 2 neúspešné ActionResults?


Mám akciu formulára v mojom súbore +page.server.ts a vraciam fail, ak zlyhá overenie schémy Zod, čo funguje. Avšak, keď vraciam ďalší fail, keď PocketBase vyhodí chybu, že e-mail je už použitý, dostanem túto typovú chybu pre každé pole okrem e-mailu.

Typescript Warning
Property '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[]; }'

Otázky :

  1. Je možné odoslať viac ako 1 fail z +page.server.ts súboru?
  2. Ako môžem správne opraviť tieto typové varovania?
  3. Robím to správne, a ak nie, ako to môžem opraviť?
+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.ts
export 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, '/');
    }
};

Odpoveď č. 1

Môžete vrátiť iba jeden neúspešný výsledok.

Ak ponecháte dve výsledky zlyhania, ale chcete opraviť problém s TS, môžete deklarovať typ a tvrdiť, že chyby kontroly e-mailu mu zodpovedajú. Napr.

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' };

Všimnite si, že as Errors nezachytí nadbytočné vlastnosti. Takže ak napíšete vlastnosť nesprávne, nedostanete chybu kompilátora.

Typ errors je odvodený zo všetkých možných návratových hodnôt funkcie, takže ak najprv zlúčite všetky chyby do jedného objektu a potom vrátite iba jeden výsledok zlyhania, nesúlad typov by už mal byť vyriešený zlúčením.

Keby v Zode bola podpora asynchrónnej validácie, mohli by ste jednoducho robiť celú validáciu týmto spôsobom. Momentálne by ste to pravdepodobne museli robiť manuálne alebo použiť knižnicu na spájanie objektov.