Вариант 1: Разделить IComponentProps
Самый простой способ сделать это, вероятно, просто определить отдельные интерфейсы для ваших "реквизитов, полученных из состояния", ваших "собственных реквизитов" и ваших "реквизитов диспетчеризации", а затем использовать тип пересечения , чтобы объединить их вместе для IComponentProps
import * as React from 'react';
import { connect, Dispatch } from 'react-redux'
import { IStateStore } from '@src/reducers';
interface IComponentOwnProps {
foo: string;
}
interface IComponentStoreProps {
bar: string;
}
interface IComponentDispatchProps {
fooAction: () => void;
}
type IComponentProps = IComponentOwnProps & IComponentStoreProps & IComponentDispatchProps
class IComponent extends React.Component<IComponentProps, never> {
public render() {
return (
<div>
foo: {this.props.foo}
bar: {this.props.bar}
<button onClick={this.props.fooAction}>Do Foo</button>
</div>
);
}
}
export default connect<IComponentStoreProps, IComponentDispatchProps, IComponentOwnProps, IStateStore>(
(state, ownProps): IComponentStoreProps => {
return {
bar: state.bar + ownProps.foo
};
},
(dispatch: Dispatch<IStateStore>): IComponentDispatchProps => (
{
fooAction: () => dispatch({type:'FOO_ACTION'})
}
)
)(IComponent);
Мы можем установить общие параметры функции соединения следующим образом:
<TStateProps, TDispatchProps, TOwnProps, State>
Вариант 2: пусть ваши функции определяют ваш интерфейс Props
Другой вариант, который я видел в дикой природе, - это использование ReturnType
сопоставленного типа , чтобы позволить вашим mapX2Props
функциям фактически определить, что они вносят в IComponentProps
.
type IComponentProps = IComponentOwnProps & IComponentStoreProps & IComponentDispatchProps;
interface IComponentOwnProps {
foo: string;
}
type IComponentStoreProps = ReturnType<typeof mapStateToProps>;
type IComponentDispatchProps = ReturnType<typeof mapDispatchToProps>;
class IComponent extends React.Component<IComponentProps, never> {
//...
}
function mapStateToProps(state: IStateStore, ownProps: IComponentOwnProps) {
return {
bar: state.bar + ownProps.foo,
};
}
function mapDispatchToProps(dispatch: Dispatch<IStateStore>) {
return {
fooAction: () => dispatch({ type: 'FOO_ACTION' })
};
}
export default connect<IComponentStoreProps, IComponentDispatchProps, IComponentOwnProps, IStateStore>(
mapStateToProps,
mapDispatchToProps
)(IComponent);
Большим преимуществом здесь является то, что он немного уменьшает размер плиты котла и делает его таким образом, что у вас есть только одно место для обновления, когда вы добавляете новую составленную карту.
Я всегда держался в стороне от ReturnType
, упростите, потому что чувствует себя задом наперед, чтобы ваша реализация определяла ваш программный интерфейс "контрактами" (IMO). Почти становится слишком просто изменить ваш IComponentProps
так, как вы не собирались.
Однако, поскольку все здесь довольно автономно, это, вероятно, приемлемый вариант использования.