关于reactjs:如何通过Typescript在Formik中添加强类型字段?

How to add strongly typed field in Formik by typescript?

我试图通过Typescript在Formik react库中添加强类型,但是我没有这样做。当然,我使用了此链接,但是无法解决我的问题。
https://jaredpalmer.com/formik/docs/guides/typescript

我在这部分代码中收到此错误(})(ActivityForm);):

Argument of type '(props: IProps) => Element' is not assignable to
parameter of type 'CompositeComponent
& FormikState & FormikHelpers & FormikHandlers & FormikComputedProps &
FormikRegistration & { ...; }>'. Type '(props: IProps) => Element' is
not assignable to type 'FunctionComponent & FormikState & FormikHelpers & FormikHandlers
& FormikComputedProps & FormikRegistration & { ...; }>'. Types of
parameters 'props' and 'props' are incompatible. Property
'setEditMode' is missing in type 'FormikSharedConfig<{}> & FormikState
& FormikHelpers & FormikHandlers & FormikComputedProps &
FormikRegistration & { ...; } & { ...; }' but required in type
'IProps'.ts(2345) ActivityForm.tsx(7, 3): 'setEditMode' is declared
here.

const ActivityForm: React.FunctionComponent Argument of type
'FunctionComponent' is not assignable to parameter of type
'CompositeComponent &
FormikState & FormikHelpers &
FormikHandlers & FormikComputedProps &
FormikRegistration & { ...; }>'. Type 'FunctionComponent' is
not assignable to type 'FunctionComponent & FormikState &
FormikHelpers & FormikHandlers &
FormikComputedProps & FormikRegistration & { ...; }>'.
Types of property 'propTypes' are incompatible.
Type 'WeakValidationMap | undefined' is not assignable to type 'WeakValidationMap &
FormikState & FormikHelpers &
FormikHandlers & FormikComputedProps &
FormikRegistration & { ...; }> | undefined'.
Type 'WeakValidationMap' is not assignable to type 'WeakValidationMap &
FormikState & FormikHelpers &
FormikHandlers & FormikComputedProps &
FormikRegistration & { ...; }>'.
Types of property 'setFormikState' are incompatible.
Type 'Validator<(f: FormikState | ((prevState: FormikState) => FormikState),
cb?: (() => void) | undefined) => void> | undefined' is not assignable
to type 'Validator<(f: FormikState | ((prevState: FormikState) => FormikState), cb?: (() =>
void) | undefined) => void> | undefined'.
Type 'Validator<(f: FormikState | ((prevState: FormikState) => FormikState),
cb?: (() => void) | undefined) => void>' is not assignable to type
'Validator<(f: FormikState | ((prevState: FormikState) => FormikState), cb?: (() =>
void) | undefined) => void>'.
Type '(f: FormikState | ((prevState: FormikState) => FormikState), cb?: (() =>
void) | undefined) => void' is not assignable to type '(f:
FormikState | ((prevState: FormikState) =>
FormikState), cb?: (() => void) | undefined) => void'.
Types of parameters 'f' and 'f' are incompatible.
Type 'FormikState | ((prevState: FormikState) => FormikState)' is not
assignable to type 'FormikState | ((prevState:
FormikState) => FormikState)'.
Type 'FormikState' is not assignable to type 'FormikState | ((prevState:
FormikState) => FormikState)'.
Type 'FormikState' is not assignable to type 'FormikState'.ts(2345) Peek Problem
No quick fixes available

此错误来自ActivityDashboard.tsx

Type '{ setEditMode: (editMode: boolean) => void; title: string;
description: string; category: string; city: string; venue: string;
date: string; }' is missing the following properties from type
'IProps': values, errors, touched, isSubmitting, and 28 more.ts(2740)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React from"react";
import * as yup from"yup";
import { withFormik, Form, Field, FormikProps } from"formik";


interface IProps {
  setEditMode: (editMode: boolean) => void;
}

export const ActivityForm = (props: IProps) => {
  const { setEditMode } = props;
  return (
    <Form>
      <Field type="text" name="title" placeholder="Title" />
      <Field
        type="text"
        rows={2}
        name="description"
        placeholder="Description"
      />
      <Field type="text" name="category" placeholder="Category" />
      <Field type="date" name="date" placeholder="Date" />
      <Field type="text" name="city" placeholder="City" />
      <Field type="text" name="venue" placeholder="Venue" />
      <button type="submit">Edit</button>
      <button type="button" onClick={() => setEditMode(false)}>
        Cancel
      </button>
    </Form>
  );
};

const myForm = withFormik({
  mapPropsToValues: props => {
    return {};
  },
  validationSchema: yup.object().shape({
    title: yup.string().required()
  }),
  handleSubmit(values) {
    console.log(values);
  }
})(ActivityForm);

export default myForm;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import React from"react";
import { IActivity } from"../../../app/models/activity";
import { ActivityList } from"./ActivityList";
import { Col, Row } from"antd";
import { ActivityDetails } from"../details/ActivityDetails";
import { ActivityForm } from"../form/ActivityForm";

interface IProps {
  activities: IActivity[];
  selectActivity: (id: string) => void;
  selectedActivity: IActivity | null;
  editMode: boolean;
  setEditMode: (editMode: boolean) => void;
  setSelectedActivity: (activity: IActivity | null) => void;
}

export const ActivityDashboard: React.FC<IProps> = ({
  activities,
  selectActivity,
  selectedActivity,
  editMode,
  setEditMode,
  setSelectedActivity
}) => {
  return (
    <Row>
      <Col span={3}></Col>
      <Col span={10}>
        <ActivityList activities={activities} selectActivity={selectActivity} />
      </Col>
      <Col span={1}></Col>
      <Col span={6}>
        {selectedActivity && !editMode && (
          <ActivityDetails
            activity={selectedActivity}
            setEditMode={setEditMode}
            setSelectedActivity={setSelectedActivity}
          />
        )}
        {editMode && (
          <ActivityForm
            setEditMode={setEditMode}
            title="alex"
            description="hi"
            category="human"
            city="newyork"
            venue="sd"
            date="2019"
          />
        )}
      </Col>
    </Row>
  );
};

我认为这里有多个问题会导致TypeScript编译器发出混乱的消息:

  • 首先,确保您的功能组件扩展了React.FC<Props>类型,以便TypeScript知道这是一个React组件:

    1
    2
    3
    4
    import * as React from 'react';

    export const ActivityForm : React.FC<IProps> = (props) => {
    ...
  • 然后,您必须从formik包中将IProps类型扩展为FormikProps类型,因为withFormik方法仅接受支持从该类型扩展的React组件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import { FormikProps } from 'formik';

    interface MyFormValues {
      title: string;
      category: string;
      description: string;
    }

    interface IProps extends FormikProps<MyFormValues> {
      setEditMode(arg: boolean): void;
    }
  • 然后,您的最终代码应如下所示(确保将缺少的属性添加到MyFormValues界面中):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    import * as React from 'react';
    import { withFormik, Form, Field, FormikProps } from 'formik';
    import * as Yup from 'yup';

    interface MyFormValues {
      title: string;
      category: string;
      description: string;
      ...
    }

    interface IProps extends FormikProps<MyFormValues> {
      setEditMode(arg: boolean): void;
    }

    export const ActivityForm: React.FC<IProps> = props => {
      const { setEditMode } = props;
      return (
        <Form>
          <Field type="text" name="title" placeholder="Title" />
          <Field
            type="text"
            rows={2}
            name="description"
            placeholder="Description"
          />
          <Field type="text" name="category" placeholder="Category" />
          <Field type="date" name="date" placeholder="Date" />
          <Field type="text" name="city" placeholder="City" />
          <Field type="text" name="venue" placeholder="Venue" />
          <button type="submit">Edit</button>
          <button type="button" onClick={() => setEditMode(false)}>
            Cancel
          </button>
        </Form>
      );
    };

    const myForm = withFormik({
      mapPropsToValues: props => {
        return {};
      },
      validationSchema: Yup.object().shape({
        title: Yup.string().required()
      }),
      handleSubmit(values) {
        console.log(values);
      }
    })(ActivityForm);

    export default myForm;

    这里还有一个带有最终代码的CodeSandbox:https://codesandbox.io/s/stackoverflow59057524-s9ouc?module = / src / ActivityForm.tsx