Amplify-js: Observable type would be better to export from '@aws-amplify/api'

Created on 11 May 2020  路  7Comments  路  Source: aws-amplify/amplify-js

Is your feature request related to a problem? Please describe.
I always import Observable type from 'zen-observable-ts' to use GraphQL Subscription with Typescript like below.

import { API, graphqlOperation } from "aws-amplify"
import { GraphQLResult } from "@aws-amplify/api";
import { Observable } from './../node_modules/zen-observable-ts';

But I would like to rather import Observable like this, which looks more natural

import { GraphQLResult, Observable } from "@aws-amplify/api";

Describe the solution you'd like
My suggestion is super simple, which export Observable at '@aws-amplify/api-graphql' like this

index.d.ts

export { Observable } from 'zen-observable-ts';
export interface GraphQLResult<T = object> {
    data?: T;
    errors?: [object];
    extensions?: {
        [key: string]: any;
    };
}
API feature-request

Most helpful comment

This problem still exists and I think the solution from @manueliglesias is valid - could we implement it?

All 7 comments

@kopkunka55 This makes sense. Can you share more of your snippet using Observable from ./../node_modules/zen-observable-ts? I'm interested to see how you're using it in your code, so I can get the right tests for it.

Thanks!

Hi, @ericclemmons
basically, I often use GraphQL subscription like below in React with Typescript

import { OnCreateTodoSubscription } from "./API";
import { API, graphqlOperation } from "aws-amplify";
import { Observable } from './../node_modules/zen-observable-ts';

useEffect(() => {
    const pubSubClient = API.graphql(
      graphqlOperation(onCreateTodo)
    ) as Observable<object>;
    const subscription = pubSubClient.subscribe({
      next: (value: GraphQLResult<OnCreateTodoSubscription>) => {
       // something to store the date to a state
      },
    });
    return () => {
      subscription.unsubscribe();
    };
  }, []);

Thanks!

Ooh, I see! I made a demo here:

https://codesandbox.io/s/aws-amplifyamplify-jsissues5741-ssq5p?file=/src/App.tsx

Without it, the TypeScript error for API.graphql(...).subscribe is:

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

@manueliglesias Is there a way we can solve this via TypeScript (see below), or do we need to rely on explicit casting (e.g. as Observable<object>) as seen above?

https://github.com/aws-amplify/amplify-js/blob/b4b40aa62644ea3688068e4e64f4573c568677a0/packages/api-graphql/src/GraphQLAPI.ts#L173-L183

Making a note here: we'll need to update our lint and test scripts accordingly to test for this error, then correcting the type.

See an example here: 84286be109d7f50eac83a9694e75b61500cc8a83

@manueliglesias Is there a way we can solve this via TypeScript (see below), or do we need to rely on explicit casting (e.g. as Observable<object>) as seen above?

Unfortunately we can't solve this via TypeScript, since the return type depends on a runtime inspection of the GraphQL operation type.

We could explore the option of having two methods instead of one, e.g.:

function graphql(
  options: GraphQLOptions,
  additionalHeaders: Record<string, string>
): Promise<GraphQLResult>;
function graphqlSubscription(
  options: GraphQLOptions,
  additionalHeaders: Record<string, string>
): Observable<GraphQLResult>;

This problem still exists and I think the solution from @manueliglesias is valid - could we implement it?

Having the same issue and having to use // @ts-ignore would love a fix

Was this page helpful?
0 / 5 - 0 ratings

Related issues

romainquellec picture romainquellec  路  3Comments

TheRealRed7 picture TheRealRed7  路  3Comments

cgarvis picture cgarvis  路  3Comments

cosmosof picture cosmosof  路  3Comments

oste picture oste  路  3Comments