jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
33.97k stars 2.79k forks source link

Return Types for useFormik #2924

Open fny opened 3 years ago

fny commented 3 years ago

We make use of useFormik to bind formik to another UI library, Everything works swimmingly. One issue though, is that there is no common return type for useFormik

// Consider
const example = useFormik<any>({ initialValues: {}, onSubmit: () =>{} })

// This is the type if example
const example: {
    initialValues: any;
    initialErrors: FormikErrors<unknown>;
    initialTouched: FormikTouched<unknown>;
    initialStatus: any;
    handleBlur: {
        (e: FocusEvent<any>): void;
        <T = any>(fieldOrEvent: T): T extends string ? (e: any) => void : void;
    };
    ... 32 more ...;
    submitCount: number;
}

It would be useful if there was a common interface for this value.

I believe it's equivalent to FormikState<any> & FormikComputedProps<any> & FormikHelpers<any> & FormikHandlers but I'm not sure.

I propose adding the following to the types file if it's actually a complete representation of useFormik's output.

type FormikInstance<Values> = FormikState<Values> & FormikComputedProps<Values> & FormikHelpers<Values> & FormikHandlers
johnrom commented 3 years ago

Agreed

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

JMA12 commented 3 years ago

I'm also looking for this one

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

alanszp commented 3 years ago

+1 want me to make a PR? Can you give me some advice?

johnrom commented 3 years ago

The types for Formik in v2 aren't set up to easily generate a complete return type. useFormik has a complete return type in my v3 branch. You can check it out here

This consists of:

FormikApi & FormikConfig

Which ultimately breaks down to

type FormikApiAndConfig = 
    // API
    FormikHelpers & 
    FormikHandlers & 
    FormikRegistration & 
    FormikFieldHelpers & 
    { getValueFromEvent } &  
    // Config
    FormikValidationConfig<Values> & 
    { enableReinitialize: boolean } &
    FormikState; // replaced with FormikStateHelpers in v3

Some of those types are newly created in my v3 branch so you'd have to dig deep to recreate them for v2.

In v3 these types are spread across two contexts, FormikContext (FormikApi) and FormikConfigContext (FormikConfig).

alanszp commented 3 years ago

Making it:

Base on your types:

All this comments are based on v2 code

type FormikApiAndConfig = 
    // API
    FormikHelpers &  --> same
    FormikHandlers &  ---> same
    FormikRegistration &  --> same 
    FormikFieldHelpers &  --> didn't find in your commit. Used FormikComputedProps 
    { getValueFromEvent } &  --> not returned by useFormik v2
    // Config
    FormikValidationConfig<Values> &  --> didn't exist; extracted as a type from FormikSharedConfig
    { enableReinitialize: boolean } & --> not returned by useFormik v2
    FormikState; // replaced with FormikStateHelpers in v3 --> same
github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

basile-savouret commented 3 years ago

Hello @fny , @johnrom. I did export type Formik = ReturnType<typeof useFormik> isn't this what you were looking for?

johnrom commented 3 years ago

@basile-savouret typeof automatically removes generics. These two are not the same:

const formikVal: ReturnType<typeof useFormik> = useFormik({ hello: string });
const typedFormikVal = useFormik({ hello: string });

One is FormikApi<any> and the other is FormikApi<{ hello: string }>. Even if that wasn't the case, there is the additional issue that not every value returned from useFormik is well-defined, but many are inferred by typescript. Defining the return type in TypeScript solves this issue as well.

basile-savouret commented 3 years ago

It's true. It works out for me because i don't need the generics handle by formik.

johnrom commented 3 years ago

The generic helps to prevent "wild guesses" when it comes to Field names and such, especially in the typed v3.1 PR #3152 which you can test here:

https://www.npmjs.com/package/@johnrom/formik-v3/v/3.1.0-types12

if you're not using completely dynamic data, I'd recommend trying it out as it can help discover bugs that haven't been discovered yet. I would locate type issues using that package and then push to production using the Formik production version you're already using.

Both that PR and the v3.0 PR #3231 have a strongly typed return value already.