Definitelytyped: @types/redux-form: I can't get it passing type check

Created on 13 Sep 2017  路  12Comments  路  Source: DefinitelyTyped/DefinitelyTyped

I tried using the @types/[email protected] package and had problems (am I doing something wrong):

import * as React from 'react';
import { reduxForm, FormProps } from 'redux-form';

@reduxForm({ form: 'test-form' })
// [ts]
// Argument of type 'typeof ShareModalForm' is not assignable to parameter of type 'ComponentType<InjectedFormProps<{}, {}>>'.
//   Type 'typeof ShareModalForm' is not assignable to type 'StatelessComponent<InjectedFormProps<{}, {}>>'.
//     Type 'typeof ShareModalForm' provides no match for the signature '(props: InjectedFormProps<{}, {}> & { children?: ReactNode; }, context?: any): ReactElement<any> | null'.
export class MyForm extends React.Component<FormProps> {
  render() {
    return <form onSubmit={this.props.onSubmit}>test</form>;
    // [ts]
    // Type '{ onSubmit: FormSubmitHandler<{}, {}> | undefined; children: string; }' is not assignable to type 'DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>'.
    //   Type '{ onSubmit: FormSubmitHandler<{}, {}> | undefined; children: string; }' is not assignable to type 'FormHTMLAttributes<HTMLFormElement>'.
    //     Types of property 'onSubmit' are incompatible.
    //       Type 'FormSubmitHandler<{}, {}> | undefined' is not assignable to type 'EventHandler<FormEvent<HTMLFormElement>> | undefined'.
    //         Type 'FormSubmitHandler<{}, {}>' is not assignable to type 'EventHandler<FormEvent<HTMLFormElement>> | undefined'.
    //           Type 'FormSubmitHandler<{}, {}>' is not assignable to type 'EventHandler<FormEvent<HTMLFormElement>>'.
  }
}

Authors: @carsonf @aikoven @LKay @bancek @alsiola

Most helpful comment

@testerez thank you very much I solved my issues! For me, it was a little bit tricky because I use es6 classes for my react components and I am not familiar with the redux compose function. In addition to that I use the JSS feature from material-ui-next and there I have to wrap my component with the withStyles HOC for getting my style classes working. This compose function is a really nice and clean thing. :thumbsup:

The only thing that I changed is that I wrote an default export. So I don't have to create a extra constant and name it (in your example MyForm) for exporting the component:

export default compose(
    reduxForm({form: 'employeeDateSelect'}),
    withStyles(styles)
)(EmployeeDateSelect); // ES6 class

All 12 comments

Like the error message says, you have incorrect types provided as submit handler. Can't tell more without seeing actual code.

This is all the code... I think that this example should compile. But maybe I'm not using the types as intended... onSubmit is coming from FormProps interface imported from @types/[email protected]

BTW I have 2 errors in my example.

This is incorrect: React.Component<FormProps>, FormProps are reserved to use with Form component. You should be using InjectedFormProps here.

Thanks! this is in fact fixing the second error but not the first one:

import * as React from 'react';
import { reduxForm, InjectedFormProps } from 'redux-form';

@reduxForm({ form: 'test-form' })
// [ts]
// Unable to resolve signature of class decorator when called as an expression.
//   Type 'DecoratedComponentClass<{}, Partial<ConfigProps<{}, {}>>>' is not assignable to type 'typeof MyForm'.
//     Types of parameters 'props' and 'props' are incompatible.
//       Type 'InjectedFormProps<{}, {}> | undefined' is not assignable to type 'Partial<ConfigProps<{}, {}>> | undefined'.
//         Type 'InjectedFormProps<{}, {}>' is not assignable to type 'Partial<ConfigProps<{}, {}>> | undefined'.
//           Type 'InjectedFormProps<{}, {}>' is not assignable to type 'Partial<ConfigProps<{}, {}>>'.
//             Types of property 'asyncValidate' are incompatible.
//               Type '() => void' is not assignable to type '((values: {}, dispatch: Dispatch<any>, props: InjectedFormProps<{}, {}>, blurredField: string) =>...'.
//                 Type '() => void' is not assignable to type '(values: {}, dispatch: Dispatch<any>, props: InjectedFormProps<{}, {}>, blurredField: string) => ...'.
//                   Type 'void' is not assignable to type 'Promise<any>'.
export class MyForm extends React.Component<InjectedFormProps> {
  render() {
    return <form onSubmit={this.props.handleSubmit}>test</form>;
  }
}

I gave up on the decorator syntax and use compose. Fixes my typing issue.

Oh, I just noticed you're using decorator @reduxForm syntax. This is still not fully specified and experimental feature in Typescript. Use HOC way of decorating your component.

It's what I did (with compose) 馃憤
Thanks for the answer!

@testerez I'm getting the same errors as you. Could you please post your working code where you get no compile errors? Especially the decorate/compose part of your component with reduxForm would be interesting. Thank you!

@npeham something like:

import * as React from 'react';
import { reduxForm, InjectedFormProps } from 'redux-form';
import { compose } from 'redux';

const MyFormView = ({ handleSubmit }: InjectedFormProps) => (
  <form onSubmit={handleSubmit}>test</form>
);

export const MyForm = compose(
  reduxForm({ form: 'test-form' }),
)(MyFormView);

// or simply
// export const MyForm = reduxForm({ form: 'test-form' })(MyFormView);

note that the compose is not really needed here because we have a single HOC.

@testerez thank you very much I solved my issues! For me, it was a little bit tricky because I use es6 classes for my react components and I am not familiar with the redux compose function. In addition to that I use the JSS feature from material-ui-next and there I have to wrap my component with the withStyles HOC for getting my style classes working. This compose function is a really nice and clean thing. :thumbsup:

The only thing that I changed is that I wrote an default export. So I don't have to create a extra constant and name it (in your example MyForm) for exporting the component:

export default compose(
    reduxForm({form: 'employeeDateSelect'}),
    withStyles(styles)
)(EmployeeDateSelect); // ES6 class

Here how I'm solved this issue for anyone that still wondering, basically same with solution above. Using InjectedFormProps

import React, { Component } from "react";
import { Field, reduxForm, InjectedFormProps } from "redux-form";
import { Input } from "reactstrap";
import { connect } from "react-redux";

class ComponentsNavbar extends Component<InjectedFormProps, {}> {
  renderField = ({ input }: any) => {
    return <Input type="text" {...input} />
  };

  render() {
    return (
      <Field name="search" component={this.renderField} />
    );
  }
}

const formWrapper = reduxForm({ form: "search" })(Navbar);

export default connect(null)(formWrapper);

Reproduced on stackblitz with reduxForm HOC

Was this page helpful?
0 / 5 - 0 ratings

Related issues

demisx picture demisx  路  3Comments

ArtemZag picture ArtemZag  路  3Comments

JWT
svipas picture svipas  路  3Comments

victor-guoyu picture victor-guoyu  路  3Comments

fasatrix picture fasatrix  路  3Comments