I am currently looking for a way to add types to the custom events emitted from the custom action to be used in use directive
I am creating. Here is the snippet.
import { z } from "zod";const acceptedNodeNames = [ //"INPUT","SELECT","TEXTAREA",];// prettier-ignoretype FormField = | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;type SubmitConfig = { schema: { [key: string]: z.Schema; };};export function form(node: HTMLFormElement, { schema }: SubmitConfig) { // store fields that needs to be validated in array const fields = Array.from(node.children).filter( (child) => acceptedNodeNames.includes(child.nodeName) && (child as FormField).name in schema, ) as FormField[]; function handleInput(this: FormField) { const { name, value } = this; const result = schema[name].safeParse(value); if (result.success) { this.removeAttribute("aria-invalid"); } else { this.setAttribute("aria-invalid", ""); } } // attach field listeners for (const field of fields) { field.addEventListener("input", handleInput); } function handleSubmit(e: SubmitEvent) { e.preventDefault(); const input = fields.reduce( (obj, field) => ({ ...obj, [field.name]: field.value, }), {}, ); const result = z.object(schema).safeParse(input); if (result.success) { const event = new CustomEvent("okay", { detail: { ...result } }); node.dispatchEvent(event); } else { const errors = JSON.parse(result.error.message); for (const error of errors) { const field = fields.find(({ name }) => name === error.path[0]); if (!field) continue; field.setAttribute("aria-invalid", ""); } const event = new CustomEvent("fail", { detail: { errors } }); node.dispatchEvent(event); } } // attach form submit handler node.addEventListener("submit", handleSubmit); return { destroy() { node.removeEventListener("submit", handleSubmit); for (const field of fields) { field.removeEventListener("input", handleInput); } }, };}
It basically just validates form field and uses zod
underneath. This is how I would like to use it.
<form novalidate method="POST" use:form={{ schema: { email: z.string().email(), }, }} on:okay={(e) => { console.log(e.detail); }} on:fail={(e) => { console.log(e.detail); }}>...</form>
This code is already working, but my only problem is that it doesn't have types and it got some annoying squiggly lines in vscode
. Is there a way at the moment to declare a type to those custom events similar to adding types in svelte components like so
interface $$Events { change: CustomEvent<{ page: number; pageSize: number; }>; }
Thanks!