Since upgrade to newest version of react-apollo the data definition on QueryProps has changed from
export interface QueryResult<TData = any, TVariables = OperationVariables> extends ObservableQueryFields<TData, TVariables> {
...
data: TData | undefined;
}
to
export interface QueryResult<TData = any, TVariables = OperationVariables> extends ObservableQueryFields<TData, TVariables> {
...
data: TData | {};
}
This is a major breaking change as all projects with updated client do not compile and fail CI. What is the reason for this change? Will this be rectified or shall we start changing our code bases? Thanks for the wonderful work you are doing guys.
Version
This was introduced by #1983. The reason was that when using data, the undefined check can be omitted. Instead of doing data && data.user you can just check data.user. Full changelog:
data was beingundefined. This behavior has been changed so that data isdata && data.user you can just check data.user) and{ data: { user } }) easier. Note: this coulddataerrors property.@tomitrescak can you provide an example of what you were doing that now doesn't compile and fails?
I had a look into this yesterday, and had a poke inside Query.test.tsx. The tests only have no issues because any test cases where the keys of the data are accessed use the Query class itself (rather than extending it), and default data to any.
I added the following (using some existing test data), and you can see that without casting the data to any, you cannot access its keys.

it('result type definition lets you access data keys', () => {
const Component = () => (
<AllPeopleQuery query={allPeopleQuery}>
{(result) => {
if (result.data && result.data.allPeople) {
return null;
}
if (result.data && result.data!.allPeople) {
return null;
}
const { allPeople } = result.data;
return null;
}}
</AllPeopleQuery>
);
});
@JakeSidSmith thanks! So now a type guard would be required instead of a simple undefined check.
Yes, it seems like a bit much though. This would have been easier with undefined.
Alternative solution (though personally I think TData | undefined makes sense).
data: TData | {[i: string]: undefined}
Which works with the above example.
Yes, please. I think the undefined check is enough. Well supported by typescript. I'm doing exactly what @JakeSidSmith and that's exactly the place where my compilation is failing.
While your undefined check can be omitted during destructure, you are losing typesafety of the data!
you have to manually now recast, importing extra types ... all that funky jazz ;(
(result as MyResultType).data // bleh
A breaking change was definitely not intended 鈽癸笍. I'll roll back to TData | undefined.
@JakeSidSmith Thanks for pointing that test issue out - I'll get that fixed. We're also putting other changes in place to prevent this from happening in the future. Thanks all - sorry for the headache!
Most helpful comment
A breaking change was definitely not intended 鈽癸笍. I'll roll back to
TData | undefined.@JakeSidSmith Thanks for pointing that test issue out - I'll get that fixed. We're also putting other changes in place to prevent this from happening in the future. Thanks all - sorry for the headache!