Definitelytyped: react-redux connect() breaks component creation

Created on 26 Apr 2017  路  6Comments  路  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the @types/react-redux package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @tkqubo, @seansfkelley @thasner

When using connect() in a React.Component, it loses its props when creating the element using TSX.

for example:

import React from 'react'
import { connect } from 'react-redux'
import { State } from '../actions'

export interface RemoteFilterProps {
  name: string;
  access: string;
  group: string;
  onSelect: FilterProps['onSelect'];
}

export class RemoteFilter extends React.Component<RemoteFilterProps, RemoteFilterState> {
  /* ... */
}

export default connect((state: State): Partial<RemoteFilterProps> => {
  return {
    access: state.access
  }
})(RemoteFilter)

when using it, it shows no props:

import RemoteFilter from './remotefilter'

export default (<RemoteFilter />) // nothing is enforced

my work around is using:

export default connect((state: State) => {
  return {
    access: state.access
  }
})(RemoteFilter) as React.ComponentClass<RemoteFilterProps>

Most helpful comment

@pocesar hmmm, not sure how to fix this in the react-redux typings.

For you, I've verified that specifying the generic type arguments gives the appropriate error:

export interface TOwnProps {
    name: string;
    group: string;
    onSelect: () => void;
}
export interface TStateProps {
    access: string;
}
type TRemoteFilterProps = TOwnProps & TStateProps;

export class RemoteFilter extends React.Component<TRemoteFilterProps, void> {
    /* ... */
}

const ConnectedRemoteFilter = connect<TStateProps, void, TOwnProps>((state: any): TStateProps => {
    return {
        access: state.access
    }
})(RemoteFilter)

const x = (<ConnectedRemoteFilter />);

(I changed some props a bit so I didn't need to import libraries for the example)

src/remote-filter.tsx(71,12): error TS2324: Property 'group' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes src/remote-filter.tsx(71,12): error TS2324: Property 'name' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes src/remote-filter.tsx(71,12): error TS2324: Property 'onSelect' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes

All 6 comments

That happens when TOwnProps (the 3rd template argument to connect) does not get an inferred type; however, TOwnProps can only be inferred if you give a function as the second argument to connect, which is actually not the most ergonomic way to use connect even with its second argument...

Indeed, this has been an issue for some time. I believe this issue is a duplicate of https://github.com/DefinitelyTyped/DefinitelyTyped/issues/8787.

export default connect((state: State): Partial<RemoteFilterProps> => {
  return {
    access: state.access
  }
})(RemoteFilter)

The typings are interpreting what you've written correctly. Returning Partial<RemoteFilterProps> from mapStateToProps indicates that all RemoteFilter props come from State. (and that all of them are optional). Therefore, no props should be passed directly as IOwnProps.

Can you type as follows:

export interface IOwnProps {
  name: string;
  group: string;
  onSelect: FilterProps['onSelect'];
}
export interface IStateProps {
  access: string;
}
type RemoteFilterProps = IOwnProps & IStateProps;

...

export default connect((state: State): IStateProps => {

...

@thasner that has the same effect, no props are passed to the decorator

@pocesar hmmm, not sure how to fix this in the react-redux typings.

For you, I've verified that specifying the generic type arguments gives the appropriate error:

export interface TOwnProps {
    name: string;
    group: string;
    onSelect: () => void;
}
export interface TStateProps {
    access: string;
}
type TRemoteFilterProps = TOwnProps & TStateProps;

export class RemoteFilter extends React.Component<TRemoteFilterProps, void> {
    /* ... */
}

const ConnectedRemoteFilter = connect<TStateProps, void, TOwnProps>((state: any): TStateProps => {
    return {
        access: state.access
    }
})(RemoteFilter)

const x = (<ConnectedRemoteFilter />);

(I changed some props a bit so I didn't need to import libraries for the example)

src/remote-filter.tsx(71,12): error TS2324: Property 'group' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes src/remote-filter.tsx(71,12): error TS2324: Property 'name' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes src/remote-filter.tsx(71,12): error TS2324: Property 'onSelect' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes

Same issue here.

Was this page helpful?
0 / 5 - 0 ratings