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

Apollo Client Libdef (also add to react-apollo) #2172

Merged
merged 5 commits into from
May 14, 2018

Conversation

TLadd
Copy link
Contributor

@TLadd TLadd commented May 5, 2018

  • Add some more tests
  • Resolve interop with the current react-apollo libdef.

It seems that since the react-apollo libdef is importing types from apollo-client (which doesn't have types), even if I include this apollo-client libdef in my project, types that react-apollo imports end up getting clobbered to any. Either need to

  1. stop importing those types in react-apollo libdef or
  2. actually use the types added here.

Actually using the types is definitely the endgame, but might be a large effort that could be split to another PR.

@TLadd TLadd force-pushed the trl/apollo-client branch 2 times, most recently from 4b99f47 to 1727d5e Compare May 8, 2018 00:30
@gantoine
Copy link
Member

gantoine commented May 9, 2018

Are the checklist items TODOs, or are they done?

@gantoine gantoine self-assigned this May 9, 2018
@gantoine gantoine added libdef Related to a library definition new labels May 9, 2018
@TLadd
Copy link
Contributor Author

TLadd commented May 9, 2018

They are TODOs. Sorry for the confusion.

@budde377
Copy link
Contributor

@TLadd let me know when you're ready for a review and I'll gladly abide. Regarding the imports; considering the poor support for inter libdef dependencies (ref #16) I'm really starting to think that the imports should be removed and the types duplicated. I'm planning on removing all the imports from react-apollo and clean up duplicate declarations during the next week.

@TLadd
Copy link
Contributor Author

TLadd commented May 10, 2018

Yeah, from #1857 (comment), it appears that even if the imports worked, the tests wouldn't. Just duplicating the types react-apollo needs is probably the path of least resistance at the moment. I think as long as we distinguish clearly in the file where the types are actually coming from (this section is actually react-apollo, this section is types from apollo-client, etc) maintenance won't be that bad.

Sorry this has been stagnating a bit; I'll have some time over the weekend to make a push and should get it to a mergeable state.

@budde377
Copy link
Contributor

budde377 commented May 10, 2018 via email

@TLadd TLadd force-pushed the trl/apollo-client branch from 7498df6 to aea7959 Compare May 12, 2018 02:34
…apollo

Add more tests for Query and Mutation components
Add tests for ApolloProvider and ApolloConsumer
@TLadd
Copy link
Contributor Author

TLadd commented May 13, 2018

@budde377 @gantoine think this is ready for a look. I copied the types from apollo-client into react-apollo as well. Sorry for the diff size.

I'm not sure how fun keeping the types in apollo-client and react-apollo in sync will be. I'm hoping it's not too bad, since it is just a matter of copy/pasting them over. If it gets to be too much of a pain, I'm not opposed to abandoning apollo-client and just maintain everything in react-apollo. At least in my projects, the only place I'm using apollo-client directly is to initialize the client (hence the tests checking ApolloClient's initialization). So not a huge deal, but I think they're worth having around if it's easy.

Added some tests focused around the Query and Mutation props I'm using.

Also some stylistic changes in the PR caused by prettier, just using the default config. I'm fine shifting the style some if there are complaints, but would prefer it be prettier-able.

Pulled both these libdefs into the project I'm using react-apollo in and seems to be behaving correctly.

Definitely still room for improvement in places, but hopefully a good step.

@budde377
Copy link
Contributor

Nice! I can prob. do a review monday afternoon (CET) :)

@TLadd TLadd changed the title Apollo Client Libdef Apollo Client Libdef (also add to react-apollo) May 14, 2018
/** End From graphql */

declare export interface ApolloProviderProps<TCache> {
client: any; // ApolloClient<TCache>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Any or apollo client?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The trouble with using ApolloClient is that it's a class and it's nominally typed. So even though ApolloClient is the same in both the apollo-client and react-apollo libdefs, they are different types. We could maybe make it work with an interface in react-apollo, but didn't think it was worth it to diverge from what is defined in apollo-client.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see... Let's leave it as is for now.

Copy link
Contributor

@budde377 budde377 left a comment

Choose a reason for hiding this comment

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

Nice work! I do not mind your style changes and love the extensions to the test suite. This libdef also works in my projects. I'll approve 👍

@TLadd
Copy link
Contributor Author

TLadd commented May 14, 2018

@gantoine Looks like this is ready for you whenever you get the time. Thanks!

@jedwards1211
Copy link
Contributor

jedwards1211 commented Aug 2, 2018

@TLadd using data: TData | {||} | void no longer works with recent versions of Flow; it errors on any property you try to access on data, because no properties are present in {||}, and recent versions of Flow no longer allow any kind of untyped property access, even in existence checks. (Without casting to any or Object at least)

Are you sure Apollo can pass an empty object?

If so would you be okay with us changing this to ?$Shape<TData>?

@jedwards1211
Copy link
Contributor

Example of the problem (Try flow link):

@flow
type Data = {foo: number} | {||}

function getFoo(data: Data): ?number {
  return data.foo
}
4:   return data.foo
                 ^ Cannot get `data.foo` because property `foo` is missing in object type [1].
References:
3: function getFoo(data: Data): ?number {
                         ^ [1]

jedwards1211 added a commit to jedwards1211/flow-typed that referenced this pull request Aug 2, 2018
… of flow

react-apollo passes an empty object before data is loaded; data will never be undefined.

However, using `| {||}` just isn't going to work with recent versions of flow (see flow-typed#2172 (comment))

I think `$Shape<TData>` is the only viable option here.
@TLadd
Copy link
Contributor Author

TLadd commented Aug 2, 2018

I believe this has always been the case (you still get an error if you select older versions of flow as well).

I'm typically checking that values are present when I'm accessing them, and it removes the type errors. This works for instance:

type Data = {foo: number} | {||}

function getFoo(data: Data): ?number {
  if (data.foo) {
  	return data.foo 
  }
  return null
}

Having said that, it may be reasonable to change data to just be TData | void. The | {||}, while correct, doesn't buy much.

@jedwards1211
Copy link
Contributor

jedwards1211 commented Aug 2, 2018

@TLadd actually I read the react-apollo source, it never passes an undefined value, not anymore at least.

I didn't realize flow has that obscure exception for checking if an object is exact empty or not. Thanks for pointing that out.

Quite subtle because if (data.foo) does error if type Data = {||}...

@TLadd
Copy link
Contributor Author

TLadd commented Aug 2, 2018

@jedwards1211 There is actually still one case where undefined gets passed in: apollographql/react-apollo#1977

Typescript actually types data as TData | undefined (https://github.com/apollographql/react-apollo/blob/master/src/Query.tsx#L97) because they couldn't figure out a way to get the equivalent of {||}. It's possible that we should follow suit and just do TData | void; might make it a little more user friendly, since that error you were showing in that example can be a bit confusing.

The only trouble with doing that is suddenly

if (data) {
  data.field.whatever
}

would typecheck, since the if check would refine it to type TData, but it might actually be the empty object.

@jedwards1211
Copy link
Contributor

Ah right. Argh...

@ganemone
Copy link
Contributor

@TLadd using data: TData | {||} | void no longer works with recent versions of Flow; it errors on any property you try to access on data, because no properties are present in {||}, and recent versions of Flow no longer allow any kind of untyped property access, even in existence checks. (Without casting to any or Object at least)

Are you sure Apollo can pass an empty object?

If so would you be okay with us changing this to ?$Shape<TData>?

I think we can actually fix this using $ObjMap (try flow link)

I will submit a PR.

@jedwards1211
Copy link
Contributor

jedwards1211 commented Oct 18, 2018

@ganemone I don't get it, the way you're using $ObjMap does almost same thing as $Shape right?
Huh, nevermind, using $Shape bizarrely doesn't cause the intended error, but $ObjMap does...

@jedwards1211
Copy link
Contributor

jedwards1211 commented Mar 13, 2019

@TLadd I don't think you were the one to introduce this, but can a MutationFunction really resolve to undefined? The return type is Promise<void | FetchResult<...>> which adds another pesky null check I really wish I could avoid.

@TLadd
Copy link
Contributor Author

TLadd commented Mar 13, 2019

It's the same in the typescript defs: https://github.com/apollographql/react-apollo/blob/master/src/Mutation.tsx#L62

Not sure; would have to look through the source to see how/if this can happen.

@jedwards1211
Copy link
Contributor

No worries, just wanted to check if you knew off the top of your head, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libdef Related to a library definition new work in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants