在Sveltekit中,你可以返回两个失败的ActionResults吗?

huangapple go评论70阅读模式
英文:

In Sveltekit, can you return 2 fail ActionResults?

问题

  1. +page.server.ts文件中是否可以发送多个失败响应?
  2. 如何正确修复这些类型警告?
  3. 如果不正确,我应该如何修复它?

+page.svelte文件中的类型警告是由于 TypeScript 在检查对象的属性时发现了问题。您可以通过以下方式来解决这些类型警告:

  1. 使用条件检查: 在使用对象的属性之前,最好使用条件检查确保属性存在。这可以防止 TypeScript 报告属性不存在的错误。
{#if form?.errors?.password}
	<!-- ^^^没有类型错误 -->
	<span class="label-text-alt text-error">{form?.errors?.password[0]}</span>
	<!-- ^^^没有类型错误 -->
{/if}
  1. 类型断言: 如果您确定某些属性存在,您可以使用类型断言来告诉 TypeScript 在这些属性上执行操作。
{#if (form?.errors as { password?: string[] })?.password}
	<!-- ^^^没有类型错误 -->
	<span class="label-text-alt text-error">{(form?.errors as { password?: string[] })?.password[0]}</span>
	<!-- ^^^没有类型错误 -->
{/if}
  1. 修改数据结构: 如果可能的话,您可以修改数据结构,以使 TypeScript 更容易理解。这可能需要对服务器端的数据结构进行调整,以匹配客户端的预期类型。

+page.server.ts 文件中,您可以看到在出现电子邮件已经存在的错误时,您返回了一个失败响应,但是这个错误的结构与表单验证失败的错误结构不同。这也可能导致 TypeScript 报告类型错误。您可以尝试统一错误结构,使它们具有一致的属性,以避免类型错误。

请注意,为了更好地解决问题,可能需要查看更多关于 registerSchema 和其他代码部分的详细信息。

英文:

I have a form action in my +page.server.ts file and I am returning a fail if it fails the zod schema validation which is working. However, when I returning another fail when PocketBase throws an error of email already in use, I get this type error for every field expect email.

Typescript Warning

Property &#39;password&#39; does not exist on type &#39;{ password?: string[] | undefined; passwordConfirm?: string[] | undefined; email?: string[] | undefined; name?: string[] | undefined; terms?: string[] | undefined; } | { email: string[]; }&#39;.
  Property &#39;password&#39; does not exist on type &#39;{ email: string[]; }&#39;

Questions:

  1. Is it possible to send more than 1 fail from a +page.server.ts file?
  2. How can I properly fix these type warnings?
  3. Am I doing this correctly, if not how can I fix it?

+page.svelte

...
	&lt;input id=&quot;password&quot;
           name=&quot;password&quot;
    	   type=&quot;password&quot;
		   placeholder=&quot;Password&quot;
		   class=&quot;input input-bordered w-full&quot; 
    /&gt;
    &lt;label class=&quot;label&quot; for=&quot;password&quot;&gt;
		{#if form?.errors?.password}
                       &lt;!--^^^Type Error Here--&gt;
			&lt;span class=&quot;label-text-alt text-error&quot;&gt;{form?.errors?.password[0]}&lt;/span&gt;
                                                               &lt;!--^^^Type Error Here--&gt;
		{/if}
	&lt;/label&gt;
...
//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 }) =&gt; {
		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(&#39;users&#39;).create(formData);
			await locals.pb.collection(&#39;users&#39;).authWithPassword(formData.email, formData.password);
		} catch (e) {
			if (e instanceof ClientResponseError) {
				const data = {
					data: rest,
                    errors: {
                          email: [&#39;Email already exists&#39;]
				    }
				};
				return fail(400, data);
			}
			throw error(500, &#39;Something went wrong&#39;);
		}
		throw redirect(303, &#39;/&#39;);
	}
};

答案1

得分: 2

只有返回一个失败的结果。

如果保留了两个失败的结果,但希望修复 TS 问题,您可以声明一个类型并断言电子邮件检查的错误符合它。例如:

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),
});

// 这匹配 Zob 验证的错误
type Errors = Partial&lt;Record&lt;keyof typeof formData, string[]&gt;&gt;;

const result = schema.safeParse(formData);
if (!result.success) {
    return fail(400, {
        errors: result.error.flatten().fieldErrors,
    });
}

if (formData.email == &#39;exists@example.com&#39;) {
    return fail(400, {
        errors: {
            email: [&#39;already exists&#39;],
        } as Errors, // 这确保了错误类型相同
    });
}

return { message: &#39;ok&#39; };

请注意,as Errors 不会捕捉多余的属性。因此,如果拼写错误属性,不会得到编译器错误。

“errors” 类型是从函数的所有可能返回值派生的,因此如果首先将所有错误合并为一个对象并只返回一个失败的结果,类型不匹配应该已经通过合并来处理。

如果 Zod 支持异步验证,您可以通过这种方式进行完整验证。目前,您可能需要手动执行验证,或使用对象合并库。

英文:

You can only return one fail result.

If you keep the two failure results, but want to fix the TS issue, you could declare a type and assert that the errors of the email check conform to it. E.g.

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&lt;Record&lt;keyof typeof formData, string[]&gt;&gt;;

const result = schema.safeParse(formData);
if (!result.success) {
    return fail(400, {
        errors: result.error.flatten().fieldErrors,
    });
}

if (formData.email == &#39;exists@example.com&#39;) {
    return fail(400, {
        errors: {
            email: [&#39;already exists&#39;],
        } as Errors, // This ensures that the errors type is the same
    });
}

return { message: &#39;ok&#39; };

Note that as Errors will not catch extraneous properties. So if you misspell a property you do not get a compiler error.

The type of errors is derived from all possible returned values of the function, so if you first merge all errors into one object and only return one failure result, the type mismatch should already be taken care of by the merging.

If there were async validation support in Zod, you could just do the full validation that way. Right now you probably would have to do it manually or use an object merging library.

huangapple
  • 本文由 发表于 2023年2月19日 10:35:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75497660.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定