Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type instantiation is excessively deep and possibly infinite with componentized fields #463

Open
1 task done
fzembow opened this issue Aug 9, 2024 · 7 comments
Open
1 task done
Labels
bug Something isn't working question Further information is requested types Something related to types

Comments

@fzembow
Copy link

fzembow commented Aug 9, 2024

  • Before posting an issue, read the FAQ and search the previous issues.

Description

I'm trying to even further componentize the approach in the componentization guide, by allowing users to pass an array of the FormPathLeaves to render the form fields.

However, I'm seeing a TS error, "Type instantiation is excessively deep and possibly infinite" when trying to use FormPathLeaves as a variable, rather than hardcoding it. You can see three parallel approaches in the below snippet.

<script lang="ts">
  import { z } from 'zod';
  import type {
    SuperValidated,
    Infer,
    FormPathLeaves,
  } from 'sveltekit-superforms';
  import { superForm } from 'sveltekit-superforms';
  import TextField from './TextField.svelte';

  export const userFormSchema = z.object({
    name: z.string().default('Hello world!'),
    email: z.string().email(),
  });

  type UserFormSchema = typeof userFormSchema;

  export let data: SuperValidated<Infer<UserFormSchema>>;
  const pathLeaves: FormPathLeaves<Infer<UserFormSchema>>[] = ['name', 'email'];

  const constPathLeaves = ['name', 'email'] as const;

  const form = superForm(data);
  const { enhance } = form;
</script>

<form method="POST" use:enhance>
  {#each pathLeaves as field}
    <!-- TS error: Type instantiation is excessively deep and possibly infinite. -->
    <TextField superform={form} {field} />
  {/each}

  <!-- Directly specifying the values is fine. -->
  <TextField superform={form} field="name" />
  <TextField superform={form} field="email" />

  {#each constPathLeaves as field}
    <!-- Using "as const" is also fine. -->
    <TextField superform={form} {field} />
  {/each}

  <div><button>Submit</button></div>
</form>

This may very well be some limitation of my typescript knowledge... but is this just not intrinsically possible? Should I be listing out the paths with a different type annotation?

If applicable, a MRE

See this example, which has the error on Sveltelab when you view the LoginForm.svelte file: EXAMPLE

@fzembow fzembow added the bug Something isn't working label Aug 9, 2024
@ciscoheat
Copy link
Owner

I can't see any LoginForm.svelte in the example link?

@ciscoheat ciscoheat added the question Further information is requested label Aug 13, 2024
@fzembow
Copy link
Author

fzembow commented Aug 13, 2024

@ciscoheat I'm sorry - I guess sveltelab didn't save my changes earlier :(

Here is a corrected repro link: https://www.sveltelab.dev/fh9ym08604bfrxv

If you click into LoginForm.svelte now, the issue will appear
image

Again, this might be a limitation of Typescript (or my knowledge thereof) but I am very thankful that you would take a look -- to me, extending the componentization even further was the natural thing to do.

@ciscoheat
Copy link
Owner

I see now, I should have looked closer at the code example. You need const, otherwise it will treat each value as string and that will probably mess up the typing. The types behind the scenes are quite complicated, especially with generics.

I did manage to remove the error once locally, so try updating to latest typescript (and maybe latest svelte 5) and maybe it will work.

@ciscoheat ciscoheat added the types Something related to types label Aug 13, 2024
@macmillen
Copy link

I have the same problem

@fzembow
Copy link
Author

fzembow commented Oct 22, 2024

FWIW I've just upgraded to svelte5 and all my other packages to latest and I can no longer reproduce the original issue.

@fzembow fzembow closed this as completed Oct 22, 2024
@macmillen
Copy link

macmillen commented Nov 6, 2024

This still happens to me with Svelte 5:

Screenshot_20241106_123022

radio-item.svelte

<script lang="ts" generics="T extends Record<string, unknown>">
  import type { FormPathLeaves, SuperForm } from "sveltekit-superforms";
  import RadioInput from "./radio-input.svelte";

  interface Props {
    superForm: SuperForm<T>;
    field: FormPathLeaves<T>;
    value: string | number;
  }

  let { superForm, field, value }: Props = $props();
</script>

<RadioInput {superForm} {field} {value}></RadioInput>

radio-input.svelte

<script lang="ts" generics="T extends Record<string, unknown>">
  import type { FormPathLeaves } from "sveltekit-superforms";
  import { fieldProxy, type SuperForm } from "sveltekit-superforms";

  interface Props {
    superForm: SuperForm<T>;
    field: FormPathLeaves<T>;
    value: string | number;
  }

  let { superForm, field, value }: Props = $props();

  const groupValue = fieldProxy(superForm, field);

  let id = $derived(`${value}-${field}`);
</script>

<input {id} type="radio" class="peer sr-only" name={field} {value} bind:group={$groupValue} />

@fzembow fzembow reopened this Nov 26, 2024
@fzembow
Copy link
Author

fzembow commented Nov 26, 2024

You're right, I'm still seeing this :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working question Further information is requested types Something related to types
Projects
None yet
Development

No branches or pull requests

3 participants