React redux typescript: connect has missing type error

This how I do it in a Typescript Redux App (adjusted to your code but not tested)

edited with comment below

  1. type connect with props for the Connected Component (ConnectedHelloWorldProps)

    const ConnectedHelloWorld:React.ComponentClass<ConnectedHelloWorldProps>  = 
        connect<any,any,HelloWorldProps>(mapStateToProps)(HelloWorld)
    
    interface ConnectedHelloWorldProps { }
    
    interface HelloWorldProps extends ConnectedHelloWorldProps {
        count: number
        ....
    }
    
  2. use the connected component and its ConnectedHelloWorldProps props in the Provider

    <Provider store={store}>
        <ConnectedHelloWorld/>
    </Provider>
    

Note: this works fine with these typings

"@types/react": "^0.14.52",
"@types/react-dom": "^0.14.19",
"@types/react-redux": "^4.4.35",
"@types/redux-thunk": "^2.1.32",

ConnectedHellowWorldProps is not really needed here, since it is an empty interface, but in a real world scenario it is likely to contain a few props.

The basic principle is this: ConnectedHelloWorldProps contain what needs to be passed at the Provider level. In mapStateToProps and/or mapDispatchToProps, enrich the actual Component HelloWorldProps with whatever is needed

Redux Typescript typings are a beast but what is shown above should be sufficient.

export declare function connect<TStateProps, TDispatchProps, TOwnProps>(
mapStateToProps: FuncOrSelf<MapStateToProps<TStateProps, TOwnProps>>,
 mapDispatchToProps?: FuncOrSelf<MapDispatchToPropsFunction<TDispatchProps, TOwnProps> | MapDispatchToPropsObject>): ComponentDecorator<TStateProps & TDispatchProps, TOwnProps>;


 interface ComponentDecorator<TOriginalProps, TOwnProps> {
    (component: ComponentClass<TOriginalProps> | StatelessComponent<TOriginalProps>): ComponentClass<TOwnProps>;
 }

Your problem is that HelloWorldState is defined like this

interface HelloWorldState {
  clickCount: number
}

And the props you want to return from mapStateToProps are

{ 
  count: state.clickCount
}

But you override the return-type as HelloWorldState, so the return type does not contain count but clickCount.


fromJS breaks type safety

ImmutableJS.fromJS works pretty bad with TypeScript type inference:

const state = Immutable.fromJS({
  count: 0
})

Here state is of type any so you don't have any error when assigning it as a return value of type HelloWorldState.


mapStateToProps should return a simple object

mapStateToProps can return a simple object, as you won't directly edit this state from the component:

const mapStateToProps = (state: AppState): HelloWorldState => {
  return {
    count: state.clickCount
  }
}

Here you will have the error you did not have when using ImmutableJS, telling you that you cannot assign { count: number } to { clickCount: number }.

So just remove the return type, and type-inference will do the job, or add the correct type.

const mapStateToProps = (state: AppState) => {
  return {
    count: state.clickCount
  }
}

Statically-typed tree structural-sharing with Monolite

I also recommend you to use Monolite which is a simple set of functions written in TypeScript and designed to be used with Redux states.

It allows you to also define your state with simple JavaScript objects, and to make updates on the state through simple functions.

import { set } from 'monolite'

const state = {
  clickCount: 0
}

const newState = set(state, _ => _.clickCount)(value => value + 1)

P.S. I'm the author of Monolite