{"action":"created","issue":{"url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped/issues/8787","repository_url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped","labels_url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped/issues/8787/labels{/name}","comments_url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped/issues/8787/comments","events_url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped/issues/8787/events","html_url":"https://github.com/DefinitelyTyped/DefinitelyTyped/issues/8787","id":144688052,"number":8787,"title":"react-redux's connect can cause wrapped components to lose all meaningful typing on props","user":{"login":"seansfkelley","id":2101409,"avatar_url":"https://avatars.githubusercontent.com/u/2101409?v=3","gravatar_id":"","url":"https://api.github.com/users/seansfkelley","html_url":"https://github.com/seansfkelley","followers_url":"https://api.github.com/users/seansfkelley/followers","following_url":"https://api.github.com/users/seansfkelley/following{/other_user}","gists_url":"https://api.github.com/users/seansfkelley/gists{/gist_id}","starred_url":"https://api.github.com/users/seansfkelley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seansfkelley/subscriptions","organizations_url":"https://api.github.com/users/seansfkelley/orgs","repos_url":"https://api.github.com/users/seansfkelley/repos","events_url":"https://api.github.com/users/seansfkelley/events{/privacy}","received_events_url":"https://api.github.com/users/seansfkelley/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2016-03-30T18:56:50Z","updated_at":"2016-04-05T20:11:23Z","closed_at":null,"body":"There is an issue with the react-redux typings such that if you leave out the `TOwnProps` parameters to both `mapStateToProps` and `mapDispatchToProps`, you can end up with a wrapped component that will freely accept any set of props (literally anything). This issue is with the newest version of react-redux as of this writing; which were last touched 56295f5058cac7ae458540423c50ac2dcf9fc711.\r\n\r\nSo here's a snippet that erroneously compiles fine:\r\n\r\n```tsx\r\ninterface OwnProps {\r\n  foo: string;\r\n}\r\n\r\ninterface ConnectedProps {\r\n  bar: string;\r\n}\r\n\r\nclass FooComponent extends React.Component<OwnProps & ConnectedProps, {}> {\r\n  render() {\r\n    return <div/>;\r\n  }\r\n}\r\n\r\nfunction mapStateToProps(state: any): ConnectedProps {\r\n  return {\r\n    bar: 'baz'\r\n  };\r\n}\r\n\r\nconst WrappedFoo = connect(mapStateToProps)(FooComponent);\r\n\r\n// Missing `foo` but also specifying unknown property `quux`; this compiles fine.\r\nReact.createElement(WrappedFoo, { quux: 10 });\r\n```\r\n\r\nYou can work around it by typecasting the result of `connect`, and everything works as expected:\r\n\r\n```tsx\r\nconst WrappedFoo = connect(mapStateToProps)(FooComponent) as React.ComponentClass<OwnProps>;\r\n```\r\n\r\nOr you can mention `OwnProps` in `mapStateToProps`:\r\n\r\n```tsx\r\nfunction mapStateToProps(state: any, ownProps: OwnProps): ConnectedProps {\r\n  return {\r\n    bar: 'baz'\r\n  };\r\n}\r\n\r\nconst WrappedFoo = connect(mapStateToProps)(FooComponent);\r\n```\r\n\r\nA couple definitions:\r\n- `OwnProps`: This is the type of the parameters that the connected version of the component accepts. That is, those that the parent must provide that aren’t auto-injected.\r\n- `ConnectedProps`: This is the type of the parameters that are selected by `mapStateToProps`. It’s not strictly necessary to the typings or the workaround, but it helps clarify when debugging since it allows you to properly type `mapStateToProps`.\r\n\r\nWhat I think is happening here is that when the optional `TOwnProps` seen in the signature of `mapStateToProps` and `mapDispatchToProps` is absent (as it is in the example), Typescript falls back on inferring `TOwnProps` as `{}`. The output of the whole process (after running `connect`) thus ends up as `React.ComponentClass<{}>`, at which point all bets are off, since `{}` accepts anything and everything.\r\n\r\nFor similar reasons, you also shouldn't specify something very lenient for `OwnProps`, such as the empty interface, which is functionally identical to `{}`. The only workaround for explicitly specifying \"no own props\" as far as I can tell is to use the typecast method to cast it to `React.ComponentClass<void>` (though probably with an intermediate `any` cast, since Typescript doesn't accept the `void` cast).\r\n\r\nI tried to tweak the typings to fix this, but I wasn't able to find a better way to define `TOwnProps`. Thoughts, @tkqubo (as the listed maintainer)?"},"comment":{"url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped/issues/comments/205972600","html_url":"https://github.com/DefinitelyTyped/DefinitelyTyped/issues/8787#issuecomment-205972600","issue_url":"https://api.github.com/repos/DefinitelyTyped/DefinitelyTyped/issues/8787","id":205972600,"user":{"login":"seansfkelley","id":2101409,"avatar_url":"https://avatars.githubusercontent.com/u/2101409?v=3","gravatar_id":"","url":"https://api.github.com/users/seansfkelley","html_url":"https://github.com/seansfkelley","followers_url":"https://api.github.com/users/seansfkelley/followers","following_url":"https://api.github.com/users/seansfkelley/following{/other_user}","gists_url":"https://api.github.com/users/seansfkelley/gists{/gist_id}","starred_url":"https://api.github.com/users/seansfkelley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seansfkelley/subscriptions","organizations_url":"https://api.github.com/users/seansfkelley/orgs","repos_url":"https://api.github.com/users/seansfkelley/repos","events_url":"https://api.github.com/users/seansfkelley/events{/privacy}","received_events_url":"https://api.github.com/users/seansfkelley/received_events","type":"User","site_admin":false},"created_at":"2016-04-05T20:11:23Z","updated_at":"2016-04-05T20:11:23Z","body":"Does that work? It seems like it would be subject to the same flaws as the existing method, if `TOwnProps` never gets mentioned in `mapStateToProps` or `mapDispatchToProps`.\r\n\r\nAlso, the return type of the decorator is not right; you want the component yielded at the end of the process to just be a `React.ComponentClass<TOwnProps>`.\r\n\r\nI tried playing around with this a while before I first filed the bug and wasn't able to come up with a better scheme than the workarounds I first presented."}}