I'm using React 18 with Redux 8 and Typescript. I want to create a component that allows the caller to pass in one of the arguments, but the other two arguments are derived from state. So I created this file ...
type OrderItemComponentProps = {
contact: Contact | undefined;
isAuthenticated: boolean;
orderItem: OrderItem;
}
const OrderItemComponent: React.FC<OrderItemComponentProps> = ({ contact, isAuthenticated, orderItem }) => {
...
}
function mapStateToProps(state: RootState, ownProps: OrderItemComponentProps): OrderItemComponentProps {
return {
contact: ownProps.contact, // passed as a prop to the container
isAuthenticated: state.auth.isAuthenticated, // derived from Redux state
orderItem: state.orderItem.orderItem // derived from Redux state
}
}
export const OrderItemContainer = connect(mapStateToProps)(OrderItemComponent)
In a separate file, I invoke the above using
<OrderItemContainer contact={orderItem.sender} />
But this generates the Typescript error
Type '{ contact: Contact | undefined; }' is missing the following properties from type '{ contact: Contact | undefined; isAuthenticated: boolean; orderItem: OrderItem; context?: Context<ReactReduxContextValue<any, AnyAction>> | undefined; store?: Store<...> | undefined; }': isAuthenticated, orderItem
What is the right way to type my "mapStateToProps" function so properly allow a declaration of this component?
Unfortunately, the type definition of
connectis weird. The most straightforward way to approach this is to split the type definition between what is returned frommapStateToPropsand parentprops. Luckily,ReturnTypeallows you to infer the interface ofmapStateToProps. Then use type casting to force the resulting component to only need the parent props, which iscontact. It should look something like this