Apollo-client: TypeScript error when using client without react

Created on 11 Sep 2020  路  11Comments  路  Source: apollographql/apollo-client

Intended outcome:
Using the client without react should not result in an error.
Note I do NOT want to enable skipLibCheck as this could hide actual problems.

Actual outcome:
The following errors occur:

node_modules/@apollo/client/utilities/observables/Observable.d.ts:1:8 - error TS1259: Module '".../node_modules/@types/zen-observable/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

1 import Observable from 'zen-observable';
         ~~~~~~~~~~

  node_modules/@types/zen-observable/index.d.ts:69:1
    69 export = Observable;
       ~~~~~~~~~~~~~~~~~~~~
    This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.

node_modules/@apollo/client/react/context/ApolloConsumer.d.ts:1:19 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

1 import React from 'react';
                    ~~~~~~~

node_modules/@apollo/client/react/context/ApolloContext.d.ts:1:19 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

1 import React from 'react';
                    ~~~~~~~

node_modules/@apollo/client/react/context/ApolloProvider.d.ts:1:19 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

1 import React from 'react';
                    ~~~~~~~

node_modules/@apollo/client/react/types/types.d.ts:2:27 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

2 import { ReactNode } from 'react';
                            ~~~~~~~

node_modules/@apollo/client/react/types/types.d.ts:144:63 - error TS2503: Cannot find namespace 'JSX'.

144     children?: null | ((result: SubscriptionResult<TData>) => JSX.Element | null);

How to reproduce the issue:
Reproduction repo: https://github.com/MatthiasKunnen/apollo-client-no-react-reproduction.

Versions

  System:
    OS: Linux 5.0 Ubuntu 18.04.5 LTS (Bionic Beaver)
  Binaries:
    Node: 12.18.0 - ~/.nvm/versions/node/v12.18.0/bin/node
    Yarn: 1.22.0 - ~/.nvm/versions/node/v12.18.0/bin/yarn
    npm: 6.14.4 - ~/.nvm/versions/node/v12.18.0/bin/npm
  Browsers:
    Chrome: 85.0.4183.83
    Firefox: 80.0.1
  npmPackages:
    @apollo/client: ^3.1.5 => 3.1.5 
    apollo-angular: ^2.0.0 => 2.0.4 
    apollo-link-scalars: ^1.0.1 => 1.0.1 
    typescript: 4.0.2

Most helpful comment

Instead of importing from @apollo/client, you can import from @apollo/client/core to get everything except the React-dependent stuff.

All 11 comments

Instead of importing from @apollo/client, you can import from @apollo/client/core to get everything except the React-dependent stuff.

That fixes all the react issues, thanks!

The downside here is that the TypeScript import helper will import only from @apollo/client so it would be required to add a linter rule banning imports of @apollo/client to prevent people from mistakenly using the wrong import. Could this be changed so that react specific imports come from @apollo/client/react?

I still have this error, don't know if it's typescript 4 related... it worked fine before I re-created my new project with angular-cli 10.1.1 and typescript 4.0.2 with strict, maybe I changed some code in the graphql module class but I don't quite remember, but now my project is broken so any help would be greatly appreciated.

this is my graphql.module.ts code:

import { APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLink } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import {environment} from '../environments/environment';
import {NgModule} from '@angular/core';
import {ApolloClientOptions} from 'apollo-client';
import {setContext} from 'apollo-link-context';

// tslint:disable-next-line:no-any
function getNewToken(): any {
  return 'abc';
}

// @ts-ignore
const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
    if (graphQLErrors) {
      for (const err of graphQLErrors) {
        switch (err.extensions?.code) {
          case 'UNAUTHENTICATED':
            // error code is set to UNAUTHENTICATED
            // when AuthenticationError thrown in resolver

            // modify the operation context with a new token
            const oldHeaders = operation.getContext().headers;
            operation.setContext({
              headers: {
                ...oldHeaders,
                authorization: getNewToken(),
              },
            });
            // retry the request, returning the new observable
            return forward(operation);
        }
      }
      // @ts-ignore
      graphQLErrors.map(({ message, locations, path }) =>
        console.log(
          `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
        ),
      );
    }

    if (networkError) {
      console.log(`[Network error]: ${networkError}`);
      // if you would also like to retry automatically on
      // network errors, we recommend that you use
      // apollo-link-retry
    }
  }
);


const uri = environment.graphQlUri;
// tslint:disable-next-line:no-any
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  const basic = setContext((operation, context) => ({
    headers: {
      Accept: 'charset=utf-8'
    }
  }));

  const auth = setContext(async (_, { headers }) => {
    // Grab token if there is one in storage or hasn't expired
    const token = null; // TODO: need to implement

    if (!token) {
      return {headers: {}};
      // An observable to fetch a new token
      // Converted .toPromise()
    } else {
      // Return the headers as usual
      return {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      };
    }
  });

  // @ts-ignore
  const link = ApolloLink.from([errorLink, basic, auth, httpLink.create({ uri })]);
  const cache = new InMemoryCache();

  return {
    link,
    cache
  };
}

@NgModule({
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink],
    },
  ],
})
export class GraphQLModule {}

and my package.json is this:

{
  "name": "mycocktailworld-client",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular-material-extensions/password-strength": "^7.0.0",
    "@angular-material-extensions/select-country": "^2.2.0",
    "@angular/animations": "~10.1.1",
    "@angular/cdk": "^10.2.0",
    "@angular/common": "~10.1.1",
    "@angular/compiler": "~10.1.1",
    "@angular/core": "~10.1.1",
    "@angular/flex-layout": "^10.0.0-beta.32",
    "@angular/forms": "~10.1.1",
    "@angular/material": "^10.2.0",
    "@angular/platform-browser": "~10.1.1",
    "@angular/platform-browser-dynamic": "~10.1.1",
    "@angular/router": "~10.1.1",
    "@apollo/client": "^3.0.0",
    "@swimlane/ngx-charts": "^16.0.0",
    "angulartics2": "^10.0.0",
    "apollo-angular": "^2.0.4",
    "apollo-angular-link-http": "^1.11.0",
    "apollo-cache-inmemory": "^1.6.6",
    "apollo-client": "^2.6.10",
    "apollo-link": "^1.2.14",
    "apollo-link-context": "^1.0.20",
    "apollo-link-error": "^1.1.13",
    "cookieconsent": "^3.1.1",
    "graphql": "^15.3.0",
    "graphql-tag": "^2.11.0",
    "moment": "^2.27.0",
    "momentjs": "^2.0.0",
    "ngx-avatar": "^4.0.0",
    "ngx-cookieconsent": "^2.2.3",
    "ngx-mask": "^10.0.1",
    "rxjs": "~6.6.0",
    "svg-country-flags": "^1.2.7",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1001.1",
    "@angular/cli": "~10.1.1",
    "@angular/compiler-cli": "~10.1.1",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.0.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
  }
}

any ideas ?
thanks

@kfirufk well, you're not importing from @apollo/client/core as mentioned in this issue and without any details about what's broken it's hard to help. If changing the import does not work I recommend creating a separate issue for your problem.

@MatthiasKunnen - thanks for your prompt response
yeah i forgot to paste the code where I changed the import, gonna create another issue. thanks

@MatthiasKunnen - I started eliminating stuff in my project and i found out that in one of my components I had

import {ApolloError} from '@apollo/client';

so the @apollo/client thingy was imported elsewhere and I didn't notice :) thanks for helping me resolve this.

The TSLint import-blacklist rule can help you prevent that.
For ESLint check no-restricted-imports.

I agree, if package.json has react as dev-dependency and as an optional peer dependency for version compatibilities.. then hoc-utils.ts should not import React from 'react';

We are using @apollo/client/core everywhere and we are still having this issue.

For us, @apollo/client/utilities is what is triggering the Observables type error as described in the issue. We need to import getMainDefinition, which is not exported in @apollo/client/core.

The real problem seems to be that the import Observable in Observables.ts is not compatible with downstream uses unless allowSyntheticDefaultImports is enabled.

I believe the fix for this should be in Observables.ts:

https://github.com/apollographql/apollo-client/blob/3b1510151d18baaa2740fbb1db14a5ba25ec11ef/src/utilities/observables/Observable.ts#L1

-import Observable from 'zen-observable';
+import * as Observable from 'zen-observable';

This would allow the import to work successfully regardless of the value of allowSyntheticDefaultImports.

@bbugh, your issue is separate from this one and has already been discussed here: #7004. It will be fixed when switching to RxJS, you can track the progress of that here: #5749.

Is this issue related to #1093? Since upgrading the package @vue/apollo-composable from 4.0.0-alpha.10 to 4.0.0-alpha.12 we get TS errors...

Was this page helpful?
0 / 5 - 0 ratings