Is there a way to add type safety to page form store in SvelteKit?

29 Views Asked by At

I separated my HTML into two files, +page.svelte and Role.svelte. This is so it's cleaner and more maintainable as I will add more svelte files into +page.svelte in the future. Role.svelte contains the form.

I've read that since form is only passed to +page.svelte and not to any components, instead of using let form: ActionData in Role.svelte I should just use $page.form by itself on Role.svelte. An issue I'm encountering is $page.form doesn't have type safety and type inference unlike ActionData. How can I make $page.form have the same inference as let form: ActionData without sacrificing the file organization?

(Here is the code):

Role.svelte

<script lang="ts">
  import { enhance } from "$app/forms";
  import { page } from "$app/stores";
  import type { ActionData } from "./$types";
  let form: ActionData = $page.form // tried, returned undefined
  form = form // did not change anything
  let userRoles = ["admin", "student"];
</script>

<form method="post" action="?/role" use:enhance>
  <!-- did not work, had to use $page.form which again has no typing -->
  {#if form?.noSelectedRole}
    <p>{form?.error}</p>
  {/if}

  <p>You are a/an...</p>
  {#each userRoles as userRole}
    <input type="radio" value={userRole} name="role" />
    <label for={userRole}>{userRole}</label>
    <br />
  {/each}

  <slot />
  <!-- For when the school can't be found -->

  <p>What school are you a part of? Type its DepEd school ID.</p>
  <input type="text" name="schoolId" placeholder="School" />
  <br />
  <button type="submit">Check</button>
</form>

+page.svelte

<script lang="ts">
  import { page } from "$app/stores";
  import type { ActionData } from "./$types";
  import Role from "./Role.svelte";
  let form: ActionData = $page.form // did not work
</script>

<Role>
  <p>
    <!-- undefined, had to use $page.form but again, no typing :( -->
    {console.log(form?.noSelectedRole)}
    {#if form?.noSelectedRole}
      Select a role please.
    {/if}
  </p>
</Role>

+page.server.ts

import type { Actions } from "./$types";
import { fail, redirect } from '@sveltejs/kit';

export const actions = {
    role: async ({ request }) => {
        const formData = await request.formData()
        const userRole = formData.get("role") as string
        const schoolId = formData.get("schoolId") as string

        console.log(`role: ${userRole}`)
        console.log(`school id: ${schoolId}`)

        if (typeof userRole !== "string" ||
            userRole == null) {
            console.log("no user role selected")
            return fail(400, {
                noSelectedRole: true,
                error: "Please select a role.",
                data: {...{userRole, schoolId}}
            })
        }
    }
} satisfies Actions;
0

There are 0 best solutions below