Vue-apollo: How to use in a project that is setup using Vue CLI@3 and TypeScript?

Created on 16 Nov 2018  路  12Comments  路  Source: vuejs/vue-apollo

td;dr
How do I include vue-apollo in a project that already uses TypeScript?

I created a fresh vue project using vue cli@3 and using typescript.

Then I added the vue-apollo plugin which modified my main.ts file to add

apolloProvider: createProvider(),

in the vue instance creation.

But the compiler complains about this.

Argument of type '{ router: VueRouter; store: Store<{}>; apolloProvider: { provide: () => {}; }; render: (h: CreateElement) => VNode; }' is not assignable to parameter of type 'ComponentOptions, DefaultMethods, DefaultComputed, PropsDefinition>, Record>'.

Object literal may only specify known properties, and 'apolloProvider' does not exist in type 'ComponentOptions, DefaultMethods, DefaultComputed, PropsDefinition>, Record>'. [2345]

I can see that there is a types directory in the vue-apollo package I fetched from npm but not sure how to use them.

I also get the following

[ts] Could not find a declaration file for module '@/vue-apollo'. '/Users/praveen/code/voicezen/repos/voicezen-ui/src/vue-apollo.js' implicitly has an 'any' type. [7016]

for the following import in main.ts

import { createProvider } from '@/vue-apollo';

I get that this might be coming from the noImplicitAny rule but then changing the generated vue-apollo.js to vue-apollo.ts also doesn't solve the problems.

Changing it to .ts removes the compiler errors from main.ts about the above two but then I get the following.

Could not find a declaration file for module 'vue-cli-plugin-apollo/graphql-client'. '/Users/praveen/code/voicezen/repos/voicezen-ui/node_modules/vue-cli-plugin-apollo/graphql-client/index.js' implicitly has an 'any' type.

for

import {
  createApolloClient,
  restartWebsockets
} from 'vue-cli-plugin-apollo/graphql-client';

To fix this, I can add a module declaration in my typings like this but is that the right way?

declare module 'vue-cli-plugin-apollo/graphql-client';

and the onLogin or onLogout param apolloClient starts complaining about them being implicitly any type too.

Most helpful comment

@praveenpuglia
I have made PR to deal with that.
https://github.com/Akryum/vue-apollo/pull/447

For now, please ignore error report on typescript.

@Akryum
I'm sorry to bother you though, I would be grateful if you would check that PR. 馃檱

All 12 comments

@praveenpuglia
I guess we have to improve vue-cli-plugin-apollo to deal with it.

https://github.com/Akryum/vue-cli-plugin-apollo

For now, you can define like below codes on main.ts to fix error report.

// add module import and define apolloClient type
import { ApolloClient } from "apollo-client";
import { SubscriptionClient } from "subscriptions-transport-ws";
import { InMemoryCache } from "apollo-cache-inmemory";

type VueApolloClient = ApolloClient<InMemoryCache> & {
  wsClient: SubscriptionClient;
};

//... some codes ...

// set apolloClient type
export async function onLogin(apolloClient: VueApolloClient, token: string) {
  //...
}

// Manually call this when user log out
export async function onLogout(apolloClient: VueApolloClient) {
  //...
}

Thanks for the comment. This really helps!

I have one more small doubt.

for onLogin and onLogout, if I have multiple clients, do I need to call resetStore on all the clients?

If so, how do I pass all clients to say, onLogout while calling from a component or store?

I tried this.$apollo.provider.clients and this.$apolloProvider.clients both of which result in type errors even though the clients exist there.

Currently this is what I'm doing:

const clients = this.$apollo.provider.clients
for (const client of Object.keys(clients)) {
  await clients[client].resetStore()
}

@quentinus95 this works, but TS complains about this.$apollo.provider doesn't have clients.

@praveenpuglia
I have made PR to deal with that.
https://github.com/Akryum/vue-apollo/pull/447

For now, please ignore error report on typescript.

@Akryum
I'm sorry to bother you though, I would be grateful if you would check that PR. 馃檱

Thanks so much! Really waiting for this to get merged.

Hi,

I'm facing a similar issue to this. I install a new project using the cli + typescript and have done these same workarounds, but even after that I'm getting the below errors (multiples) and can't seem to find anything regarding this. Any info you can provide is appreciated; I'm new to Typescript, but need to use it for this project. Thanks in advance!

ERROR in /Users/jeissler/Projects/www/vue-test-3/node_modules/apollo-client/data/store.d.ts
34:17 Cannot use namespace 'ExecutionResult' as a type.
    32 |     markMutationResult(mutation: {
    33 |         mutationId: string;
  > 34 |         result: ExecutionResult;
       |                 ^
    35 |         document: DocumentNode;
    36 |         variables: any;
    37 |         updateQueries: {

@jeissler
it's not reproduced on my env.
could you show us full of example to repro?

@joe-re thanks for your reply; I've abandoned typescript for this project 20 days ago citing the above issues. It seems like TS isn't something that's well supported although I am still hoping to use the vue-apollo package.

Version - 3.0.0-beta.27

Hi! Thanks so much for merging the PR but I feel it still doesn't solve the problem entirely.

I do get this.$apollo.provider.clients working in Component code but each Client here is of type ApolloClient.

The onLogin or onLogout methods accept Client but it's not same as ApolloClient because it also expect wsClient int the passed in apolloClient which violates ApolloClient type signature.

How can I resolve that?

Ok, So I solve it this way. Just let me know if this is correct.

In vue-apollo.ts, I created these two.

export type VueApolloClient = ApolloClient<InMemoryCache> & {
  wsClient: SubscriptionClient;
};

export interface VueApolloClients {
  [key: string]: VueApolloClient;
}

And then in the component where I call the onLogout method, I did the following.

onLogout(this.$apollo.provider.clients as VueApolloClients);

Finally going back to vue-apollo.ts I changed the signatures of onLogin and onLogout to accept
multiple clients, loop through them and then call resetStore and restartWebsockets methods.

export async function onLogin(clients: VueApolloClients, token: string) {
  if (typeof localStorage !== 'undefined' && token) {
    localStorage.setItem(AUTH_TOKEN, token);
  }
  resetCacheAndSockets(clients);
}

async function resetCacheAndSockets(clients: VueApolloClients) {
  for (const client of Object.keys(clients)) {
    if (clients[client].wsClient) {
      restartWebsockets(clients[client].wsClient);
    }
    try {
      await clients[client].resetStore();
    } catch (e) {
      /* tslint:disable-next-line:no-console */
      console.log(
        '%cError on cache reset (logout)',
        'color: orange;',
        e.message
      );
    }
  }
}

I tried to change tsconfig

{
  "compilerOptions": {
     ..............
    "allowJs": true
  },

Please advise

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anymost picture anymost  路  3Comments

dsbert picture dsbert  路  4Comments

beeplin picture beeplin  路  4Comments

wangxiangyao picture wangxiangyao  路  4Comments

mathe42 picture mathe42  路  4Comments