Как автоматически генерировать интерфейсы машинописи для подключенных компонентов - PullRequest
3 голосов
/ 01 октября 2019

Есть ли способ автоматически расширять интерфейс подключенного компонента, используя типы mapStateToProps и mapDispatchToProps? Например, следующий код:

interface ComponentProps {
  state?: State;
  action?: (id: string) => void;
}

const mapStateToProps = (state: any) => ({
  state: state,
});

const mapDispatchToProps = (dispatch: any) => ({
  action: (id: string) => dispatch(Action),
});

const Component = (props: ComponentProps) => <div>...</div>;

export const ConnectedComponent = connect(
  mapStateToProps,
  mapDispatchToProps,
)(Component);

требует, чтобы я добавил state и action в качестве дополнительных реквизитов в мой ComponentProps, чтобы использовать их в моем компоненте, поскольку реквизиты будутбыть назначенным connect HOC.

При использовании чего-то вроде materialUI и его withStyles HOC, мы можем использовать WithStyles<typeof styles> для автоматического добавления classes проп (с точными ключами в зависимости от styles)к нашему интерфейсу, например

ComponentProps extends WithStyles<typeof styles> {
  actualProps: any;
}

const ConnectedComponent = withStyles(styles)(Component);

Можно ли сделать то же самое для connect?

1 Ответ

2 голосов
/ 05 октября 2019

Вот как это делается в response-redux-typcript-guide :

import Types from 'MyTypes';
import { bindActionCreators, Dispatch } from 'redux';
import { connect } from 'react-redux';
import * as React from 'react';

import { countersActions } from '../features/counters';

// Thunk Action
const incrementWithDelay = () => async (dispatch: Dispatch): Promise<void> => {
  setTimeout(() => dispatch(countersActions.increment()), 1000);
};

const mapStateToProps = (state: Types.RootState) => ({
  count: state.counters.reduxCounter,
});

const mapDispatchToProps = (dispatch: Dispatch<Types.RootAction>) =>
  bindActionCreators(
    {
      onIncrement: incrementWithDelay,
    },
    dispatch
  );

type Props = ReturnType<typeof mapStateToProps> &
  ReturnType<typeof mapDispatchToProps> & {
    label: string;
  };

export const FCCounter: React.FC<Props> = props => {
  const { label, count, onIncrement } = props;

  const handleIncrement = () => {
    // Thunk action is correctly typed as promise
    onIncrement().then(() => {
      // ...
    });
  };

  return (
    <div>
      <span>
        {label}: {count}
      </span>
      <button type="button" onClick={handleIncrement}>
        {`Increment`}
      </button>
    </div>
  );
};

export const FCCounterConnectedBindActionCreators = connect(
  mapStateToProps,
  mapDispatchToProps
)(FCCounter);

Вы должны использовать ReturnType помощник:

type Props = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps> {
  label: string;
};
...