Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add examples with Flowtype support + libdefs for redux and react-redux #1887

Merged
merged 4 commits into from
Sep 19, 2016
Merged

Conversation

gcanti
Copy link
Contributor

@gcanti gcanti commented Aug 9, 2016

Using Flow for statically analyzing state and actions

This PR is a proof of concept and is not meant to be merged

Added examples (ordered by difficulty)

  • counter-flow
  • todos-flow
  • todomvc-flow

Added libdefs (in the ROOT/flow-typed directory)

  • redux
  • react-redux

Observations

  1. the best type safety is achieved by avoiding the following helpers
  • combineReducers (you can miss a field and / or assign a wrong reducer to a field)
  • bindActionCreators (all action creator signatures are erased) <= this is now type safe

combineReducers may be replaced by combining the reducers by hand (see the todos-flow example). bindActionCreators is unsafe when an object is passed in. However bindActionCreators also accepts a single function which is safer (see the todomvc-flow example)

  1. react-redux's libdef was pretty hard to write. Should cover the most common cases (at least)

  2. In order to please Flow I've done some refactorings but I tried to keep them as small as possible

  3. libdefs need community feedback, then we might consider to push them to flow-typed

@timdorr
Copy link
Member

timdorr commented Aug 10, 2016

I don't think we need the examples to be run with Flow. We don't have any other examples that use TypeScript, by comparison.

I do think there is value in the Flow definitions, though. Can you open that up as a separate PR?

Edit: I DO think there's value in the defs! Whoops!

@timdorr timdorr closed this Aug 10, 2016
@gcanti
Copy link
Contributor Author

gcanti commented Aug 10, 2016

@timdorr I added the examples (and I do believe they are very important) for several reasons:

But even more important, while libdefs alone seem the main asset, examples are crucial for beginners: adding type annotations (but I'd say more in general adding type safety) is not always a straightforward process. Moreover, these examples are valuable because show the transition from an untyped codebase to a typed one.

@timdorr
Copy link
Member

timdorr commented Aug 10, 2016

We test our TypeScript defs. Is there no equivalent testing infrastructure for Flow?

All of what you're saying describes Flow-specific issues and idioms. Those could apply to any other library, not just Redux. I don't want us to take on a language extension that will be unfamiliar to beginners or indicate some pattern they should be following. In fact, this is what Dan is trying to do in #1883, where create-react-app will let us get rid of a lot of the tooling infrastructure that distracts from the important part: the code.

Also, none of regular contributors are Flow experts (otherwise, we would have done this a year ago when Dan brought it up 😄), so adding code that no one can really own isn't going to serve us well.

@gaearon
Copy link
Contributor

gaearon commented Aug 10, 2016

I would like to have a Flow example.
Not for every single example, but having something like todos-flow is something I want.
However it would need to be rebased on top of #1883 and use the same infra.

In fact, this is what Dan is trying to do in #1883, where create-react-app will let us get rid of a lot of the tooling infrastructure that distracts from the important part: the code.

I want Flow to eventually be included by default with Create React App. We might also start using it more in React docs as it becomes better suited to common workflows / stacks in the community.

I would like to reopen and re-scope this in the following way:

  • Just a single todos-flow example.
  • It should build on top of Port examples to use Create React App #1883.
  • I don’t understand how flow-typed folder works: does this mean we’ll ship Flow definitions? Or would users have to copy-paste it? I want todos-flow to work out of the box if possible. If we need to ship definitions, I’d like to do that.

@gaearon gaearon reopened this Aug 10, 2016
@timdorr
Copy link
Member

timdorr commented Aug 10, 2016

Well, my bad then. Sorry for closing!

@alexeygolev
Copy link

@gaearon flow-typed folder within a project is automatically used by flow as a libdef folder. To make it work out of the box the definitions should be shipped (Draft.js team has made some progress on that as far as I know — they ship their definitions with the lib). Another possibility is to add it to (flow-typed)[https://github.com/flowtype/flow-typed/] repo. There is a community created libdef for redux there, but having an official one is always better.

@gaearon
Copy link
Contributor

gaearon commented Aug 10, 2016

If someone is willing to lead the effort of official Flow types I’m happy to assist in any way I can.

@alexeygolev
Copy link

@gaearon I guess we just need to decide between flow-typed repo or shipping with redux

@gaearon
Copy link
Contributor

gaearon commented Aug 10, 2016

I guess we just need to decide between flow-typed repo or shipping with redux

@thejameskyle Any opinions on this?

@gcanti
Copy link
Contributor Author

gcanti commented Aug 10, 2016

@gaearon if there's something I can do I'm glad to help. I worked on this for a few weeks, when you find the right tradeoff, flow is awesome

@timdorr
Copy link
Member

timdorr commented Aug 10, 2016

@gcanti Do you mind splitting out the single commit into one for each example and the libdefs separately? Even better would be a separate PR for the definitions and the examples, but you don't have to do that. Reading through 2,675 new lines makes my browser crawl 😄

@timdorr
Copy link
Member

timdorr commented Aug 10, 2016

Thank you so much! 💯

@timdorr
Copy link
Member

timdorr commented Aug 10, 2016

So, I'm with @gaearon on keeping this to just one single example. Duplicating examples means pain whenever one is updated and you have to synchronize the changes to the other. 3 examples mean that happens 3x as often.

Given the size of the todomvc-flow example (1,560 lines of code), that one should go. I know it has some things to help with dealing with CSS imports, but that's a Flow issue, not a Redux one. So, I don't think we're in any position here to be establishing patterns for another library.

I'd be happy with either the todos-flow or counter-flow examples being added. It looks like todos-flow has more substantial Flow-specific additions (namely, a separate types definition for the app), so it seems like the better choice. What are your thoughts, @gcanti?

@gcanti
Copy link
Contributor Author

gcanti commented Aug 10, 2016

I agree, one single example is enough. counter-flow is too simple while todomvc-flow is unnecessary big.

todos-flow seems perfect, is fairly small but contains all the juice. It shows how to:

  • configure a minimal .flowconfig file
  • type check the action creators
  • type check the reducers
  • write a type safe combined reducer
  • type check stateless components
  • type check the containers and connect them via react-redux with the connector pattern
  • group the domain model in a separate file
  • tie all together by annotating the store

@kristian-puccio
Copy link

The other thing that I've been doing for this is typed check tests to go
with it.

The pattern I've used is each reducer file exports it's own state +
initialState and each corresponding test file exports some populated typed
test data.
That way in my root reducer I can combine states and in my root reducer
test file I have access to typed test state from other reducers so I can
test the selectors that select across more than one reducer.

I've never been able to get typing working for the connect HOC though so
I've been getting the mapStateToProps to export StateProps and
mapDispatchToProps to export DispatchProps.
Then my props type for the component is type Props = StateProps & DispatchProps & IncomingProps;. This works but feels super hacky.

On 11 August 2016 at 06:24, Giulio Canti [email protected] wrote:

I agree, one single example is enough. counter-flow is too simple while
todomvc-flow is unnecessary big.

todos-flow seems perfect, is fairly small but contains all the juice. It
shows how to:

  • configure a minimal .flowconfig file
  • type check the action creators
  • type check the reducers
  • write a type safe combined reducer
  • type check stateless components
  • type check the containers and connect them via react-redux with the
    connector pattern
  • group the domain model in a separate file
  • tie all together by annotating the store


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#1887 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACA_f6R9kObU267BOfxtX5UR_jjM1h-1ks5qejOEgaJpZM4JgNAn
.


declare type Store<S, A: { type: $Subtype<string> }> = {
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
dispatch: Dispatch<S, A>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't Dispatch<A> do the job as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, that S was an experiment to retain type info in favour of react-redux (I mean the dispatch function injected by connect in some cases) but I guess is unnecessary. Better to discard it and simplify both libdefs, thanks for pointing out.

@kasperpeulen
Copy link

  1. libdefs need community feedback, then we might consider to push them to flow-typed

Should I give the feedback in this PR?

@kasperpeulen
Copy link

@gcanti I have one problem with your definition, so basically when you have this:

const connector: Connector<OwnProps,Props> = connect(...)

It now works like that Props are the Props of the component. And OwnProps are the Props that the connected Component exposes. It assumes that Props = SP & { dispatch: Dispatch<S, A> } where SP are the props it gets from the redux State. But this is not true right? The props can also come from the view, it doesn't have to come from the redux state.

I get a bunch of errors of code that work, because of that (verryyy looongg error messages). But I think this is the reason.

@kasperpeulen
Copy link

kasperpeulen commented Aug 16, 2016

For example, say I have:

    <Counter style={{color: 'red'}}/>

where Counter is

type Props = {
  show: boolean,
  value: number,
  dispatch: Dispatch<State, Action>,
  style: Object
}
const Counter = ({show, value, dispatch, style}: Props) =

Now show and value is coming from the redux state like this:

const connector: Connector<{style: Object}, Props> = connect(
  ({Counter}: State) => {
    return {...Counter}
  }
);

Where Counter has type

{
  value: number,
  show: boolean
}

So everything works if I run it, but I get the following errors:

src/Counter/index.js:0
inconsistent use of library definitions
 33:   declare type Connector<OP, P> = {
                                       ^ intersection. This type is incompatible with. See lib: flow-typed/react-redux.js:33
 34:     (component: StatelessComponent<P>): ConnectedComponentClass<OP, P, void, void>;
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. See lib: flow-typed/react-redux.js:34
  Member 1:
   34:     (component: StatelessComponent<P>): ConnectedComponentClass<OP, P, void, void>;
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. See lib: flow-typed/react-redux.js:34
  Error:
   38: const connector: Connector<{style: Object}, Props> = connect(
                                                   ^^^^^ object type. This type is incompatible with. See: src/Counter/Counter.js:38
   52:   ): Connector<OP, SP & { dispatch: Dispatch<S, A> }>;
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ intersection. See lib: flow-typed/react-redux.js:52
    Member 1:
     38: const connector: Connector<{style: Object}, Props> = connect(
                                                              ^ type parameter `SP` of function call. See: src/Counter/Counter.js:38
    Error:
     38: const connector: Connector<{style: Object}, Props> = connect(
                                                     ^^^^^ property `style`. Property not found in. See: src/Counter/Counter.js:38
     40:     return {...Counter}
                    ^^^^^^^^^^^^ object literal. See: src/Counter/Counter.js:40
    Member 2:
     52:   ): Connector<OP, SP & { dispatch: Dispatch<S, A> }>;
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ object type. See lib: flow-typed/react-redux.js:52
    Error:
     38: const connector: Connector<{style: Object}, Props> = connect(
                                                     ^^^^^ property `style`. Property not found in. See: src/Counter/Counter.js:38
     52:   ): Connector<OP, SP & { dispatch: Dispatch<S, A> }>;
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ object type. See lib: flow-typed/react-redux.js:52
  Member 2:
   35:     <Def, St>(component: Class<React$Component<Def, P, St>>): ConnectedComponentClass<OP, P, Def, St>;
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ polymorphic type: function type. See lib: flow-typed/react-redux.js:35
  Error:
  inconsistent use of library definitions
   21:   declare type StatelessComponent<P> = (props: P) => ?React$Element<any>;
                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ statics of function type. Callable signature not found in. See lib: flow-typed/react-redux.js:21
   16: declare class React$Component<DefaultProps, Props, State> {
       ^ statics of React$Component. See lib: /private/tmp/flow/flowlib_377a32d6/react.js:16

src/Counter/index.js:0
inconsistent use of library definitions
 33:   declare type Connector<OP, P> = {
                                       ^ intersection. This type is incompatible with. See lib: flow-typed/react-redux.js:33
 35:     <Def, St>(component: Class<React$Component<Def, P, St>>): ConnectedComponentClass<OP, P, Def, St>;
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ polymorphic type: function type. See lib: flow-typed/react-redux.js:35
  Member 1:
   34:     (component: StatelessComponent<P>): ConnectedComponentClass<OP, P, void, void>;
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. See lib: flow-typed/react-redux.js:34
  Error:
  inconsistent use of library definitions
   34:     (component: StatelessComponent<P>): ConnectedComponentClass<OP, P, void, void>;
                       ^^^^^^^^^^^^^^^^^^^^^ function type. Callable signature not found in. See lib: flow-typed/react-redux.js:34
   35:     <Def, St>(component: Class<React$Component<Def, P, St>>): ConnectedComponentClass<OP, P, Def, St>;
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ statics of React$Component. See lib: flow-typed/react-redux.js:35
  Member 2:
   35:     <Def, St>(component: Class<React$Component<Def, P, St>>): ConnectedComponentClass<OP, P, Def, St>;
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ polymorphic type: function type. See lib: flow-typed/react-redux.js:35
  Error:
   38: const connector: Connector<{style: Object}, Props> = connect(
                                                   ^^^^^ object type. This type is incompatible with. See: src/Counter/Counter.js:38
   52:   ): Connector<OP, SP & { dispatch: Dispatch<S, A> }>;
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ intersection. See lib: flow-typed/react-redux.js:52
    Member 1:
     38: const connector: Connector<{style: Object}, Props> = connect(
                                                              ^ type parameter `SP` of function call. See: src/Counter/Counter.js:38
    Error:
     38: const connector: Connector<{style: Object}, Props> = connect(
                                                     ^^^^^ property `style`. Property not found in. See: src/Counter/Counter.js:38
     40:     return {...Counter}
                    ^^^^^^^^^^^^ object literal. See: src/Counter/Counter.js:40
    Member 2:
     52:   ): Connector<OP, SP & { dispatch: Dispatch<S, A> }>;
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ object type. See lib: flow-typed/react-redux.js:52
    Error:
     38: const connector: Connector<{style: Object}, Props> = connect(
                                                     ^^^^^ property `style`. Property not found in. See: src/Counter/Counter.js:38
     52:   ): Connector<OP, SP & { dispatch: Dispatch<S, A> }>;
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ object type. See lib: flow-typed/react-redux.js:52


Found 2 errors

@gcanti
Copy link
Contributor Author

gcanti commented Aug 16, 2016

@kasperpeulen type parameter S removed from Dispatch.

It assumes that Props = SP & { dispatch: Dispatch<S, A> } where SP are the props it gets from the redux State. But this is not true right?

Yes, theorically you are right. Technically, in order to type check as much as possible, I need that property (I tried for hours other approaches but I failed. I'm open to alternative implementation though)

I get a bunch of errors of code that work

Seems an easy fix

const connector: Connector<{style: Object}, Props> = connect(
  ({Counter}: State, {style}) => {
    return {...Counter, style}
  }
)

verryyy looongg error messages

Yeah, alas there are (5 overloadings of connect) x (2 ways of defining a component), i.e. stateless and React$Component, thus the error messages are long and awkward

@kasperpeulen
Copy link

kasperpeulen commented Aug 16, 2016

type parameter S removed from Dispatch.

Nice 👍

Yes, theorically you are right. Technically, in order to type check as much as possible, I need that property (I tried for hours other approaches but I failed. I'm open to alternative implementation though)

I see, I tried a bit as well, but I also failed getting it to work like I wanted.

Seems an easy fix

That works indeed. Strangely enough, this did not work:

const connector: Connector<{style: Object}, Props> = connect(
  ({Counter}: State, ownProps) => {
    return {...Counter, ...ownProps}
  }
)

If this will be chosen as the way to go, I think it is important to have good documentation.

type Props = {
  show: boolean,
  value: number,
  dispatch: Dispatch<State, Action>,
  style?: Object
}

That seems to work as well. In this case this is some sense better, as it seems natural to make a style property optional.

@gcanti
Copy link
Contributor Author

gcanti commented Aug 16, 2016

Strangely enough, this did not work

Yeah, kind of surprising. The spread works if you add a type annotation

type OwnProps = {
  style: Object
};

const connector: Connector<OwnProps, Props> = connect(
  ({Counter}: State, ownProps: OwnProps) => {
    return {...Counter, ...ownProps}
  }
)

@agentcooper
Copy link

@gcanti Thank you for working on this, proper definitions for react-redux are the missing piece for full Flow coverage on our project.

I'm trying to compile a simple example with your definitions: https://github.com/agentcooper/react-redux-flow-example.

App renders Counter without text prop and Flow does not seem to pick up the error. Is this solvable?

@gcanti
Copy link
Contributor Author

gcanti commented Aug 17, 2016

@agentcooper

  • move the flow-typed dir to the project root (otherwise flow doesn't see it)
  • add the // @flow pragma to types/index.js

you'll get a few errors

@agentcooper
Copy link

agentcooper commented Aug 17, 2016

@gcanti just did that and found out that I have the same issue as @kasperpeulen. It is actually working now, however merging ownProps with stateProps looks little bit awkward: agentcooper/react-redux-flow-example@0d374f7#diff-08a5a32bd874f1452a71be13b25fa610L30.


*/

declare type Dispatch<S, A> = (action: A) => A;
Copy link

@rsolomon rsolomon Aug 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this definition is a bit more rigid than the middleware API allows. For example, redux-promise would allow a Dispatch object to take a param action of type {type: T, payload: Promise<P>}, but would then return Promise<{type: T, payload: P}>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Is there a better option than returning any?

Note. The typescript definition file should be modified as well

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of anything better at the moment, since any middleware could modify this in all sorts of ways. It might be possible to pass through the definition of Dispatch from StoreEnhancer. However, I think I remember reading that a reason Flow typedefs for Redux were put on hold last year was because this was difficult to achieve.

@aaronjensen
Copy link
Contributor

How would one augment Dispatch<A> with the thunk middleware? You can't just include a thunk in A because it doesn't have a type property. Would you have to edit the types directly to do this or is there another way?

@gcanti
Copy link
Contributor Author

gcanti commented Sep 15, 2016

@kasperpeulen @MarcoPolo @jimbolla Thanks for your comments, I'm trying a new approach using the $Supertype magic type:

declare function connect<S, A, OP, SP>(
  mapStateToProps: MapStateToProps<S, OP, SP>,
  mapDispatchToProps: Null,
  mergeProps: Null,
  options?: ConnectOptions
): Connector<
    OP, 
    $Supertype< // <= this should allow the `& OP` intersection below and "optional" field declarations in the connected component (@MarcoPolo)
      SP & 
      { dispatch: Dispatch<A> } & 
      OP> // <= this should account for the default merge function (@kasperpeulen and @MarcoPolo)
  >;

Also the wrong connect overloading should be fixed (@jimbolla comment)

Could you please try / review my last commit?

Copy link
Contributor

@aaronjensen aaronjensen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new definitions still work on my current project. Nice work!

declare type Null = null | void;

declare function connect<A, OP>(
...rest: Array<void>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for? Is it necessary to ensure that the other clauses are used if any params are passed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a workaround for facebook/flow#2360

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. I had to remove them from redux-saga as they caused issues. I wonder if I introduced more issues... also is a better workaround to reorder them? Maybe they're the same...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a comment about why it's necessary to do this, with a link to the issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aaronjensen moving it to the last position doesn't work, you get "Case 4 may work: But if it doesn't, case 6 looks promising too: Please provide additional annotation(s) to determine whether case 4 works"

@jimbolla done

Copy link

@MarcoPolo MarcoPolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great!

@timdorr
Copy link
Member

timdorr commented Sep 19, 2016

OK, we've got @MarcoPolo, @aaronjensen, and @alexeygolev all saying this looks good. So, it's on you 3 if the community gets out their pitchforks 🔥 😈

But seriously, thanks for the awesome work on this @gcanti and the help from everyone who commented. Couldn't have done it without you all!

@gnoff
Copy link

gnoff commented Sep 23, 2016

@gcanti what is the best way to consume this today. I have the redux and react-redux libdef from flow-typed installed right now. Are you going to publish there? Or will this be distributed as part of the npm dep on install and we should point flow to it?

@aaronjensen
Copy link
Contributor

@gnoff they're pull requested flow-typed/flow-typed#318

@jcreamer898
Copy link

jcreamer898 commented Sep 26, 2016

I'm presently trying to grok all of this information. So, as of right NOW, there's a flow-typed directory that automatically allows me to do this...

import type { Dispatch as ReduxDispatch } from "redux";

BUT, as of flow-typed/flow-typed#318, when it gets merged, the flow-typed repo will contain the declarations, so they'll at that point be pulled from there?

AMIRITE?!

Loving the work you guys are all doing!

@gcanti
Copy link
Contributor Author

gcanti commented Oct 1, 2016

type safe combineReducers using the new $ObjMap magic type (Flow v0.33+) https://gist.github.com/gcanti/1e4494371c46f7f7ef4fb919778a32e9

@aaronjensen
Copy link
Contributor

Awesome. I'd say we should incorporate it.

@gcanti
Copy link
Contributor Author

gcanti commented Oct 2, 2016

@aaronjensen in my last version (sent to flow-typed) I also improved bindActionCreators

declare type ActionCreator<A, B> = (...args: Array<B>) => A;
declare type ActionCreators<K, A> = { [key: K]: ActionCreator<A, *> };

declare function bindActionCreators<A, C: ActionCreator<A, *>>(actionCreator: C, dispatch: Dispatch<A>): C;
declare function bindActionCreators<A, K, C: ActionCreators<K, A>>(actionCreators: C, dispatch: Dispatch<A>): C;

I'd say we should incorporate it

What about users of Flow 0.32-? As @jcreamer898 pointed out, it's not yet clear to me how to handle these things properly

@rsolomon
Copy link

rsolomon commented Oct 4, 2016

@gcanti flow-typed allows different versions for a lib via subdir. For example, redux currently has a 0.30.x subdir: https://github.com/flowtype/flow-typed/tree/master/definitions/npm/react-redux_v4.x.x

Any libs utilizing $ObjMap would presumably live under 0.33.x

Where did you send your updated definitions to? I can't find any related PRs.

@gcanti
Copy link
Contributor Author

gcanti commented Oct 5, 2016

@rsolomon I know, I was talking about redux which at the moment contains a copy of the definition files

The PR is here flow-typed/flow-typed#318

@timdorr timdorr mentioned this pull request Nov 18, 2016
8 tasks
@mull
Copy link

mull commented Jan 11, 2017

@gcanti did you ever attempt to use this with [email protected]?

@gcanti
Copy link
Contributor Author

gcanti commented Jan 11, 2017

@mull no, I didn't

@azaharakis
Copy link

@ccorcos did you ever come to a solution to the problem mentioned above:
#1887 (comment)
I tried clicking through to the repo you linked but it is no longer there.

If I understood you correctly Prop validation on a component isn't occurring when wrapped with connect. Particularly when it is getting some of it's props from it's parent. Which is what i'm seeing.

In my case my connect is partially applied so it can take different react component's. Which I can't see a good example for in this PR

@AndrewSouthpaw
Copy link

I'm having the same problem as @azaharakis, did anyone come to a solution? It's worrisome that I lose prop validation as soon as I connect my component. 🙁

@rsolomon
Copy link

@AndrewSouthpaw I've been using this for class-based components and it maintains type safety as expected. I've been meaning to submit it for PR to flow-typed, but it needs to be cleaned up to support stateless components.

It is largely lifted from the existing definitions there, but it provides much more sound type safety for me. Hopefully it can help you out.

@AndrewSouthpaw
Copy link

Wow, that's some bonafide magic right there @rsolomon, it works like a charm (I don't use stateless components), thanks for sharing. Did you come up with that yourself? I'm trying to get better at flow typing and maybe contribute to the library, but I get so lost when looking at a file like that one. What was your key change(s)?

@rsolomon
Copy link

Nah I didn't completely come up with it. It's largely based on this definition, but as written that file provided me no type safety.

I had used similar strategies for typing CSSModules and other HoCs, so I figured it could probably be implemented here. Seemed to work like a charm. Glad you found it useful :)

@rsolomon
Copy link

What was your key change(s)?

In particular, avoiding catch-all types like Object and using $Diff were the keys to the magic.

seantcoyote pushed a commit to seantcoyote/redux that referenced this pull request Jan 14, 2018
reduxjs#1887)

* libdefs

* todos-flow example

* fix react-redux libdef using the `$Supertype` magic type

* add comment to the workaround and link to the relevant issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.