svelte-forms-lib icon indicating copy to clipboard operation
svelte-forms-lib copied to clipboard

<Form {context}> produces type error with TypeScript

Open jtlapp opened this issue 4 years ago • 4 comments

Summary

With TypeScript, I would like to both use the helper components and have the values passed to my onSubmit handler be typed. In order to do this, I have to call createForm (to get type inference) and pass the resulting context to the Form helper. But when I do this I get a type error saying that my FormState type "is not assignable to type 'FormState<Record<string, any>>".

Example

The following working code produces the error:

<script lang="ts">
  import * as yup from 'yup';
  import { createForm, Form, Field, ErrorMessage } from 'svelte-forms-lib';

  const schema = yup.object().shape({
    title: yup.string().required().min(4),
    description: yup.string().required().min(10)
  });

  const context = createForm({
    initialValues: {
      title: '',
      description: ''
    },
    validationSchema: schema,
    onSubmit: (values) => {
      alert(JSON.stringify(values));
    }
  });
</script>

<Form {context}> <!-- TYPE ERROR -->
  <div>
    <label for="title">Title</label>
    <Field type="text" name="title" id="title" />
    <ErrorMessage name="title" />
  </div>
  <div>
    <label for="description">Description</label>
    <Field type="textarea" name="description" />
    <ErrorMessage name="description" />
  </div>
  <button type="submit">Submit</button>
</Form>

Here is the type error:

Type 'FormState<{ title: string; description: string; }>' is not assignable to type 'FormState<Record<string, any>>'.
  Types of property 'updateField' are incompatible.
    Type '(field: "title" | "description", value: any) => void' is not assignable to type '(field: string, value: any) => void'.
      Types of parameters 'field' and 'field' are incompatible.
        Type 'string' is not assignable to type '"title" | "description"'.

Workaround

I am using the following workaround for now, declaring the context to have type 'any':

  const context: any = createForm({ ... });

Possible fixes

I suspect that changing Record<string, any> to {[key: string]: any} in index.d.ts might correct the problem.

jtlapp avatar Nov 10 '21 19:11 jtlapp

I think you are mixing two different ways of creating the form.

When you use the Form component you just have to provide the configuration that you now put into createForm. You don't have to use createForm itself.

When you just use a plain HTML <form/> element, then you use createForm.

tylkomat avatar Nov 26 '21 14:11 tylkomat

Okay, thanks. I can make the type errors go away by doing that, but it makes too many type errors go away. Notice that I do not get a type error in the following code because the types of the initialValues properties are not inferred:

Screen Shot 2021-11-26 at 09 18 17

Notice that when I use createForm() the types of the initialValues properties are inferred:

Screen Shot 2021-11-26 at 09 19 37

Besides, the type declaration indicates that the form context is supposed to be a valid input to the Form component, and providing the form context as input actually works (aside from the type error):

export type FormProps<Inf = Record<string, unknown>> = {
  context?: FormState;
  initialValues?: Inf;
  onSubmit?: ((values: Inf) => any) | ((values: Inf) => Promise<any>);
  validate?: (values: Inf) => any | undefined;
  validationSchema?: ObjectSchema<any>;
} & svelte.JSX.HTMLAttributes<HTMLFormElement>;

/* ... */

declare class Form extends SvelteComponentTyped<
  FormProps,
  Record<string, unknown>,
  {
    default: FormState;
  }
> {}

jtlapp avatar Nov 26 '21 15:11 jtlapp

I forked the repo to experiment with a possible solution, but I get this error that I can't figure out how to resolve:

Cannot find lib definition for 'svelte2tsx'.ts(2726)

Screen Shot 2021-11-26 at 10 06 29

The TypeScript docs indicate that /// <reference lib="some-lib-name" /> is for referencing "built-in" libraries.

jtlapp avatar Nov 26 '21 16:11 jtlapp

Any update on this issue?

JoshAwaze avatar Dec 13 '23 12:12 JoshAwaze