Skip to content

Remote Function Form typechecking does not work with variant / discriminatedUnion #14667

@hrueger

Description

@hrueger

Describe the bug

Hi, in my schema, I depend on valibot's variant (I believe that is Zod's discriminatedUnion) quite a lot. This allows you to define conditions (if the user has selected type a earlier, ask for email, otherwise ask for telefone).
However, this does not work on the frontend. Or maybe I'm just doing it wrong? EDIT: It actually does work on the frontend if you do myForm.fields.myField.value == "type1" in the condition, but TypeScript complains (see below).

Reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-mpz8w8fc?file=src%2Froutes%2F%2Bpage.svelte

I'd expect that those properties either always exist or exist conditionally. However, they just don't really work at all? with the in operator, I can make TypeScript happy, but it does not work in the runtime. EDIT: The code below works at runtime, but svelte check fails. If I replace {#if myForm.fields.differing.type.value() == "a"} with {#if "propA" in myForm.fields.differing}, TS is happy, but then it does not work anymore (the condition is always false).

Schema:

export const schema = v.object({
  alwaysExisting: v.string(),
  differing: v.variant('type', [
    v.object({
      type: v.literal('a'),
      propA: v.string(),
    }),
    v.object({
      type: v.literal('b'),
      propB: v.string(),
    }),
  ]),
});

UI:

<form {...myForm}>
	Always: <input {...myForm.fields.alwaysExisting.as("text")}>
	<br>
	Differing:
	<select {...myForm.fields.differing.type.as("select")}>
		<option value="a">a</option>
		<option value="b">b</option>
	</select>

	{#if myForm.fields.differing.type.value() == "a"}
		PropA: <input {...myForm.fields.differing.propA.as("text")}>
	{:else}
		PropB: <input {...myForm.fields.differing.propB.as("text")}>
	{/if}
	<br>
	propA in myForm.fields.differing: {"propA" in myForm.fields.differing}<br>
	propB in myForm.fields.differing: {"propB" in myForm.fields.differing}<br>
</form>

Backend types (they are ok):

export const myForm = form(schema, async (data) => {
  console.log(data.alwaysExisting);
  console.log(data.differing.type);
  if (data.differing.type == 'a') {
    console.log(data.differing.propA);
  } else {
    console.log(data.differing.propB);
  }
});

Logs

-

System Info

System:
    OS: macOS 15.7.1
    CPU: (14) arm64 Apple M3 Max
    Memory: 145.41 MB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.17.0 - /Users/hannes/.nvm/versions/node/v22.17.0/bin/node
    Yarn: 4.9.3 - /Users/hannes/.nvm/versions/node/v22.17.0/bin/yarn
    npm: 11.5.2 - /Users/hannes/.nvm/versions/node/v22.17.0/bin/npm
    bun: 1.2.23 - /opt/homebrew/bin/bun
    Deno: 2.5.3 - /opt/homebrew/bin/deno
  Browsers:
    Chrome: 141.0.7390.65
    Firefox: 143.0.4
    Safari: 26.0.1
  npmPackages:
    @sveltejs/adapter-node: ^5.3.3 => 5.3.3 
    @sveltejs/kit: ^2.46.4 => 2.46.4 
    @sveltejs/vite-plugin-svelte: ^6.2.1 => 6.2.1 
    vite: 6 => 6.3.6

Severity

blocking an upgrade

Additional Information

Blocking the upgrade to using remote functions instead of my old custom validation implementation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions