Skip to content

Instantly share code, notes, and snippets.

@christianchown
Last active September 19, 2021 09:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christianchown/05e084c78ec216070a5a2b80f0534d4b to your computer and use it in GitHub Desktop.
Save christianchown/05e084c78ec216070a5a2b80f0534d4b to your computer and use it in GitHub Desktop.
ConnectedProps - the missing TypeScript helper for Redux
import { InferableComponentEnhancerWithProps } from 'react-redux';
export default type ConnectedProps<T> = T extends InferableComponentEnhancerWithProps<infer Props, infer _> ? Props : never;
// credit: https://github.com/Voronar
// use it like this
import React from 'react';
import { connect } from 'react-redux';
import ConnectedProps from './ConnectedProps';
import { State, anAction, someOtherAction } from './yourReduxStuff';
const mapStateToProps = (state: State) => ({
slice: state.slice,
otherValue: state.some.otherValue,
});
const mapDispatchToProps = { // I've used the object shorthand, but all flavours of mapDispatchToProps will work
anAction,
someOtherAction,
};
// define your connector *before* the component, so you can use ConnectedProps to extract the types
const connector = connect(mapStateToProps, mapDispatchToProps);
type PropsFromRedux = ConnectedProps<typeof connector>;
// PropsFromRedux now has your store prop types automagically inferred
function SomeComponent({ slice, otherValue, anAction, someOtherAction }: PropsFromRedux) {
return ....
}
export default connector(SomeComponent);
@christianchown
Copy link
Author

@mbohgard
Copy link

Thank you for this!

@markerikson
Copy link

FYI, the ConnectedProps<T> type was added to @types/react-redux in v7.1.2:

DefinitelyTyped/DefinitelyTyped#37300
DefinitelyTyped/DefinitelyTyped#31227

And we now have a React-Redux "Static Typing" docs page that officially recommends using this pattern:

https://react-redux.js.org/using-react-redux/static-typing

Thank you for writing this gist, btw. I came across it a few months ago while researching ways to handle types for connect, and without this example, never would have learned about it or been able to publicly document the pattern.

@mbohgard
Copy link

@markerikson Yes, I actually noticed this myself when I relied on VSCode auto import and it imported it from react-redux instead of my utility types. Thank you.

The most interesting bit though is how did you suddenly find this old gist just days after I replied? 😮

@markerikson
Copy link

I actually found it a couple months ago :) I just now replied because we now have that info in the docs.

@chadmott
Copy link

amazing thank you for this... for anyone interested in react-router + redux + TypesScript -- this is how I did it to get types working

import { RouteComponentProps, withRouter } from 'react-router-dom';

const mapStateToProps = (state: State) => ({
  someState
});

const mapDispatchToProps = {
  someFunc 
};

const connector = connect(mapStateToProps, mapDispatchToProps);
type PropsFromRedux = ConnectedProps<typeof connector>;

const MyComponent = ({
  SomeStateAsProps
}: PropsFromRedux & RouteComponentProps) => { // added the "& RouteComponentProps
return (
'working
);
}

export default connector(withRouter(MyComponent)); // <- no more squiggles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment