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

Field props are not typed #2086

Closed
iwarshak opened this issue Dec 5, 2019 · 27 comments
Closed

Field props are not typed #2086

iwarshak opened this issue Dec 5, 2019 · 27 comments

Comments

@iwarshak
Copy link

iwarshak commented Dec 5, 2019

🐛 Bug report

Current Behavior

FieldProps are not typed appropriately when using <Field>

Screen Shot 2019-12-05 at 9 29 54 AM

However, manually typing it seems to fix the warning

Screen Shot 2019-12-05 at 10 47 28 AM

I implemented the Field based on the TS guide

Expected behavior

I expected TS to not give a warning here since I followed the example of the guides.

Reproducible example

Here is a sample: https://codesandbox.io/s/hopeful-sunset-5n7ud

Suggested solution(s)

My knowledge of TS may not be deep enough to say whether it TS should error on this, or if it really is the case that I need to coerce the props to FieldProps in the last codesandbox sample.

If that's the case then the guide should be updated, and I am happy to do it and submit a PR.

Additional context

Your environment

Software Version(s)
Formik 2.0.6
React 16.2.0
TypeScript 3.7.2
Browser Chrome
npm/Yarn
Operating System Mac
@RichardLindhout
Copy link

RichardLindhout commented Dec 16, 2019

I ended up doing this:

import { Formik, Field, Form, FieldProps } from 'formik'
import TextField from '@material-ui/core/TextField'
interface FormValues {
  title: string
}
<Formik
      initialValues={initialValues}
      validationSchema={schema}
      onSubmit={onSubmit}
      render={formikBag => (
        <Form>
          <Field
            name="title"
            render={({
              field,
              form: { isSubmitting },
              meta,
            }: FieldProps<FormValues>) => (
              <TextField
                {...field}
                disabled={isSubmitting}
                type="text"
                variant="outlined"
                error={meta.touched && !!meta.error}
                helperText={meta.touched && meta.error}
                label={'Titel'}
                fullWidth
              />
            )}
          />
        </Form>
      )}
    />

@RichardLindhout
Copy link

Looks like it's a bug in TypeScript or something

@lightwave
Copy link
Contributor

If I interpret the type info in Field.d.ts correctly, render gets passed a props argument of type FieldConfig instead of FieldProps in your case. If you look at Field.d.ts, there are quite a lot of places where 'any' type is used.

@RichardLindhout
Copy link

It would be better if the unkown type was used https://mariusschulz.com/blog/the-unknown-type-in-typescript

@lightwave
Copy link
Contributor

The following definition of FieldProps is incorrect in my humble opinion. FieldInputProps and FieldMetaProps takes a type parameter of V to denote the type of a field value. However, FormikProps expects a type parameter to denote the type of the values of a form. So, in FieldProps, FormikProps shouldn't take V as the type parameter.

This hasn't caused a problem in most project, I think, primarily due to the fact that most project are using the Field component which set V to any.

However, if you start using useField in Typescript, it causes type error.

export interface FieldProps<V = any> {
  field: FieldInputProps<V>;
  form: FormikProps<V>; // if ppl want to restrict this for a given form, let them.
  meta: FieldMetaProps<V>;
}

@jaredpalmer
Copy link
Owner

Fixed in 2.1.

@AndrewPrifer
Copy link

AndrewPrifer commented Jan 14, 2020

@jaredpalmer could you please provide a minimal code snippet using <Field> with children that TypeScript shouldn't be complaining about? I'm on Formik 2.1.1 and TypeScript 3.7.4 and I'm still getting the "Binding element 'field'/'meta'/'etc' implicitly has an 'any' type." errors for the example typescript code on the Formik website.

To be honest explicit typing would make sense because without it the types derived from the type of the field value would have any type, however according to the docs it doesn't seem necessary.

@davidwilson3
Copy link

@andrewpeterprifer @jaredpalmer

This is still an issue for me too. I'm on Formik 2.1.3 and Typescript 3.7.5 and am receiving these implicit any errors.

Error example: "Binding element 'setSubmitting' implicitly has an 'any' type." Has anyone found a consistent solution to this?

@unframework
Copy link

Also experiencing the same issue with Formik 2.1.4 and Typescript 3.7.4.

@AndrewPrifer
Copy link

@davidwilson3 I think explicitly typing the field props will always be necessary because otherwise TypeScript would have absolutely no way of telling which field a certain Field component belongs to. My complaint was more directed to the documentation. @jaredpalmer maybe the Field component could be made more ergonomic by letting it accept a generic type parameter like useField does?

@delewis13
Copy link

Same issue Formik 2.1.4, typescript 3.8.3

@NicolasMarino
Copy link

Any updates on this?

Same issue in Formik 2.1.5, typescript 3.8.3

@RichardLindhout
Copy link

RichardLindhout commented Aug 24, 2020

Maybe you need to write this

<Formik<FormValues>
       abc={etc} />

@jarodburchill
Copy link

This is still not fixed in v2.2.6

@vavra7
Copy link

vavra7 commented May 9, 2021

Two years later and field props still without typing.

@bkiac
Copy link

bkiac commented Jul 16, 2021

Issue still persists in v2.2.9 with [email protected]

@johnrom
Copy link
Collaborator

johnrom commented Jul 16, 2021

It's not advisable to create a new functional component in each render to pass to the component prop, as React will not be able to tell they are the same component. If you want to use render props, it is recommended to use a child function which should be typed correctly automatically.

Types overhaul is targeted for 3.1 and a preview is possible by searching PRs for "Strongly Typed Formik v3", though your particular case is not tested as component should not be created on-the-fly.

@bkiac
Copy link

bkiac commented Jul 22, 2021

I did use render props with a child function but props is any, I used @RichardLindhout solution (#2086 (comment)) to specify the types

<Field name="period">
	{(props: FieldProps<string>) => ( // `props` is `any` without `FieldProps`
		<select {...props.field}>
			<option value="current">Current</option>
			<option value="next">Next</option>
			<option value="both">Both</option>
		</select>
	)}
</Field>

@skele2k
Copy link

skele2k commented Oct 14, 2021

One way around this problem is creating custom component and using useField hook

type InputFieldProps = InputHTMLAttributes<HTMLInputElement> & {
    label: string;
    name: string;
    textarea?: boolean;
  };

export const InputField: React.FC<InputFieldProps> = ({
    label,
    textarea,
    size: _,
    ...props
}) => {
    const [field, {error}] = useField(props); 
    ...

@lehnavid
Copy link

lehnavid commented Feb 6, 2022

Problem still occurs.
Typescript: 4.5.2
Formik: 2.2.9

@daniellin215
Copy link

daniellin215 commented Feb 11, 2022

image

@jaredpalmer given a snippet below, what types should we use? You said this is fixed but it doesn't seem so:

<Field name="lastName"> {({ field, form }) => ( <FormControl isInvalid={form.errors.lastName && form.touched.lastName} > <FormLabel color={"lightGray"} htmlFor="lastName"> Last name </FormLabel> <Input {...field} size="md" id="lastName" placeholder="Anderson" /> <FormErrorMessage>{form.errors.lastName}</FormErrorMessage> </FormControl> )} </Field>

@kimgysen
Copy link

Still a problem
Screenshot 2022-05-26 at 14 48 00

@martinbliss
Copy link

FYI Formik's documentation is misleading and should be corrected to avoid confusion by TS consumers. While Formik was written in TypeScript, this issue makes it clear that Formik does not yet support strong typing, and therefor intermediate/advanced use cases (e.g. <Field ...>{({field}) => ... } </Field>) are not yet supported for TypeScript consumers who care about strong typing. I also checked the API reference for <Field /> and it doesn't mention anything about this gap either. Surprisingly, other libraries which are strongly typed recommend Formik without mentioning this gap either.

Pages I checked just now:
https://formik.org/docs/guides/typescript
https://formik.org/docs/examples/typescript
https://formik.org/docs/api/field

@Joshuajrodrigues
Copy link

Joshuajrodrigues commented Aug 28, 2022

https://chakra-ui.com/docs/components/form-control/usage#usage-with-form-libraries

Form Libraries like Formik make it soooo easy to manage form state and validation.

well that was a lie

{({ field, form }) => (//Binding element 'field' implicitly has an 'any' type.
<FormControl isRequired
isInvalid={form.errors.name && form.touched.name}
>
Name
<Input {...field} name="name" type={"text"} />
{form.errors.name}

)}

@ODelibalta
Copy link

ODelibalta commented Jan 10, 2023

This is still an issue for me. I'd appreciate any help.

Binding element 'field' implicitly has an 'any' type.ts(7031)
"use client";

import {
  Box,
  Button,
  Checkbox,
  Container,
  FormControl,
  FormLabel,
  Heading,
  HStack,
  Input,
  Stack,
  PasswordField,
  FormErrorMessage,
} from "@myapp/ui";
import { useBreakpointValue, useColorModeValue } from "@chakra-ui/react";
import { Formik, Field, Form, FormikHelpers } from "formik";
import { object, string } from "yup";

interface Values {
  password: string;
  email: string;
}

let formSchema = object().shape({
  email: string().email().required("Email is required"),
  password: string().required("Password is required"),
});

const Login: React.FC = () => {
  const handleSubmit = (values: Values) => {
    console.log(values);
  };

  return (
    <Container
      maxW="lg"
      py={{ base: "12", md: "24" }}
      px={{ base: "0", sm: "8" }}
    >
      <Stack spacing="8">
        <Stack spacing="6">
          <Stack spacing={{ base: "2", md: "3" }} textAlign="center">
            <Heading size={useBreakpointValue({ base: "xs", md: "sm" })}>
              Log in to your account
            </Heading>
          </Stack>
        </Stack>
        <Box
          py={{ base: "0", sm: "8" }}
          px={{ base: "4", sm: "10" }}
          bg={useBreakpointValue({ base: "transparent", sm: "bg-surface" })}
          boxShadow={{ base: "none", sm: useColorModeValue("md", "md-dark") }}
          borderRadius={{ base: "none", sm: "xl" }}
        >
          <Formik
            initialValues={{
              password: "",
              email: "",
            }}
            validationSchema={formSchema}
            onSubmit={(values: Values) => handleSubmit(values)}
          >
            {({ errors }) => (
              <Form>
                <Stack spacing="6">
                  <Stack spacing="5">
                    <Field name="email" id="email" type="email">
                      {({ field, form }) => (
                        <FormControl
                          isInvalid={form.errors.email && form.touched.email}
                        >
                          <FormLabel htmlFor="email">Email</FormLabel>
                          <Input {...field} required />
                          <FormErrorMessage>
                            {form.errors.email}
                          </FormErrorMessage>
                        </FormControl>
                      )}
                    </Field>
                    <Field name="password" id="password" type="password">
                      {({ field, form }) => (
                        <FormControl
                          isInvalid={
                            form.errors.password && form.touched.password
                          }
                        >
                          <FormLabel htmlFor="password">Password</FormLabel>
                          <PasswordField {...field} />
                          <FormErrorMessage>
                            {form.errors.password}
                          </FormErrorMessage>
                        </FormControl>
                      )}
                    </Field>
                  </Stack>
                  <HStack justify="space-between">
                    <Checkbox defaultChecked>Remember me</Checkbox>
                    <Button variant="link" colorScheme="blue" size="sm">
                      Forgot password?
                    </Button>
                  </HStack>
                  <Stack spacing="6">
                    <Button
                      variant="primary"
                      disabled={errors.email || errors.password ? true : false}
                      type="submit"
                    >
                      Sign in
                    </Button>
                  </Stack>
                </Stack>
              </Form>
            )}
          </Formik>
        </Box>
      </Stack>
    </Container>
  );
};

export default Login;

@johnrom
Copy link
Collaborator

johnrom commented Jan 10, 2023

This library hasn't had activity in quite a while. You can look at my implementation here which came close to solving the problem:

#3152

But I think React Hook Form has since solved a lot of the advanced types required for forms in their library since then.

@ODelibalta
Copy link

@johnrom I really appreciate the mention of the other library. Thank you so much I am going try that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests