如何为Svelte自定义Action的自定义事件添加类型(use指令场景)
为Svelte自定义Action添加自定义事件类型
1. 导入核心类型
先从svelte/action里导入ActionReturn类型,这是定义带返回值的自定义Action的核心类型,同时按需导入zod相关类型:
import type { ActionReturn } from 'svelte/action'; import type { ZodSchema } from 'zod';
2. 声明自定义事件类型
和组件里用$$Events的思路一样,先定义一个接口来描述你的自定义事件,比如表单验证场景的两个事件:
// 自定义事件接口,对应组件里的$$Events interface ValidationEvents { // 验证成功事件,携带解析后的数据 validateSuccess: CustomEvent<{ data: Record<string, unknown> }>; // 验证失败事件,携带字段错误信息 validateError: CustomEvent<{ errors: Record<string, string[]> }>; }
3. 给Action绑定类型
在定义Action函数时,通过ActionReturn的泛型参数指定选项类型和事件类型,第三个泛型参数就是我们刚才定义的事件接口:
// 定义Action接收的选项类型 type ValidationActionOptions = { schema: ZodSchema; }; export function validate( node: HTMLElement, options: ValidationActionOptions ): ActionReturn<ValidationActionOptions, ValidationEvents> { // 表单提交处理逻辑 function handleSubmit(e: SubmitEvent) { e.preventDefault(); const formData = new FormData(node as HTMLFormElement); const data = Object.fromEntries(formData); const result = options.schema.safeParse(data); if (result.success) { // 派发验证成功事件 node.dispatchEvent(new CustomEvent('validateSuccess', { detail: { data: result.data } })); } else { // 派发验证失败事件 node.dispatchEvent(new CustomEvent('validateError', { detail: { errors: result.error.flatten().fieldErrors } })); } } node.addEventListener('submit', handleSubmit); return { update(newOptions) { options = newOptions; }, destroy() { node.removeEventListener('submit', handleSubmit); } }; }
4. 组件中使用时的类型提示
现在在Svelte组件里使用这个Action,监听自定义事件时VSCode会自动给出正确的类型提示,不会再出现无意义的波浪线:
<script lang="ts"> import { validate } from './validateAction'; import { z } from 'zod'; const loginSchema = z.object({ email: z.string().email('请输入合法邮箱'), password: z.string().min(6, '密码至少6位') }); function handleSuccess(e: CustomEvent<{ data: z.infer<typeof loginSchema> }>) { console.log('验证通过:', e.detail.data); } function handleError(e: CustomEvent<{ errors: Record<string, string[]> }>) { console.log('验证失败:', e.detail.errors); } </script> <form use:validate={{ schema: loginSchema }} on:validateSuccess={handleSuccess} on:validateError={handleError}> <input type="email" name="email" placeholder="邮箱" /> <input type="password" name="password" placeholder="密码" /> <button type="submit">登录</button> </form>
补充说明
ActionReturn的三个泛型参数依次是:Action选项类型、绑定的元素类型(可选,默认HTMLElement)、自定义事件类型(就是我们声明的事件接口)- 如果你的Action不需要接收选项,可以用
Action<never, ValidationEvents>来简化类型声明 - 自定义事件的
detail类型要和CustomEvent的泛型严格对应,这样派发和监听时都会有精准的类型提示
内容的提问来源于stack exchange,提问作者JP Calvo
相关产品推荐
相关产品推荐

