amplify-js: GraphQLResult and Observable incorrect types for API.graphql
Type 'GraphQLResult | Observable<object>' is not assignable to type '{ data: CreateDocumentMutation; }'.
  Type 'GraphQLResult' is not assignable to type '{ data: CreateDocumentMutation; }'.
    Types of property 'data' are incompatible.
      Type 'object | undefined' is not assignable to type 'CreateDocumentMutation'.
        Type 'undefined' is not assignable to type 'CreateDocumentMutation'.  TS2322

Getting the above error using typescript after the new Amplify js version.

It would be better to use Observable<any> in this case because using type object is incompatible. In TypeScript the type object is the opposite of any and is not assignable to anything.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 31
  • Comments: 32 (9 by maintainers)

Most upvoted comments

This problem popped up for me during the React Amplify tutorial https://docs.amplify.aws/start/getting-started/data-model/q/integration/react#connect-frontend-to-api

Line 23-24:

const todoData = await API.graphql(graphqlOperation(listTodos))
const todos = todoData.data.listTodos.items

The error is:

Property 'data' does not exist on type 'GraphQLResult<object> | Observable<object>'.
  Property 'data' does not exist on type 'Observable<object>'.ts(2339)

I managed to go around this problem by using this obvious kludge:

const todoData: any = await API.graphql(graphqlOperation(listTodos))

It would be nice with a proper solution though 😉

@michalmikolajczyk @selipso as you know using any disables type checking.

Until #5208 or #3748 get through, try something like this:

import { GraphQLResult } from "@aws-amplify/api";
import { ListTodosQuery } from "./api";

// ...

const todoData = (
  await API.graphql(graphqlOperation(listTodos))
) as GraphQLResult<ListTodosQuery>;

const todos = todoData.data.listTodos.items

I’m seeing a similar issue with await API.graphql(). When trying to access data from the returned result:

TS2339: Property 'data' does not exist on type 'GraphQLResult | Observable<object>'.
  Property 'data' does not exist on type 'Observable<object>'.

Same issue… changing to <any> doesn’t fix it.
The code should be generate without needing to edit it.
Any solutions?

@ffxsam I couldn’t see the code behind the popup 😦

The PR that I mentioned above should solve your problem once it’s merged. It uses generics allowing your define the structure of the variables passed and data returned.

Something like:

API.graphql<{createFolder: SOMETYPE}>(...)

Would allow you to access

result.data?.createFolder

My temporary solution might be cleaner than the ones mentioned above:

You could change this:

const result = await API.graphql(graphqlOperation(listTodos));

to this:

import { GraphQLQuery } from '@aws-amplify/api';

const result = await API.graphql<GraphQLQuery<typeof listTodos>>(graphqlOperation(listTodos));

If the import has errors, you may need to add @aws-amplify/api as a dependency in your package.json.

On the other hand, if you have a subscription:

API.graphql(graphqlOperation(onCreateTodo)).subscribe({...});

change to:

import { GraphQLQuery } from '@aws-amplify/api';

API.graphql<GraphQLSubscription<typeof onCreateTodo>>(graphqlOperation(onCreateUser)).subscribe({...});

any updates on it? I don’t like to have any type in code

any updates? seems like I always get a Promise and not Observable. It is a little annoying

we’ve solved this by adding an ‘as unknown’. If you have a better way to type, do not hesitate to share.

	(API.graphql(graphqlOperation(createAttributeMutation, { input: payload })) as unknown) as {
		data: CreateAttributeMutation
	}

@ffxsam It’s complaining about result.data.createFolder because result.data is optional. Once TypeScript 3.7 is release this will be much easier

return result.data?.createFolder;

There’s a PR to add support for generics to the API’s which helps with some of the stuff mentioned here. See #3748

There’s been much discussion about the return type of API.graphql(). Basically it’s a GraphQLResult if you’re performing a query/mutation and an Observable if you’re performing a subscription

@elorzafe lets track this for next major version

@buggy That’s actually not true, as you can see above I’m checking for falsey values for result and result.data (which is partially blocked by the popup message).

It still gives me that error. And yeah, I haven’t started using subscriptions yet, so your comment about Observable makes sense to me now.

Hello. @michalmikolajczyk Your solution is the good one. Thanks.

Also, this:

export interface GraphQLResult {
    data?: object;
    errors?: [object];
    extensions?: {
        [key: string]: any;
    };
}

I would probably change the data line to:

data?: Record<string, any>;