apollo icon indicating copy to clipboard operation
apollo copied to clipboard

Cannot use apollo in Typescript @Component decorator with 'components' key

Open tqwewe opened this issue 5 years ago • 16 comments

In my vue typescript application, I'm trying to use vue apollo with the vue-property-decorator library.

I have the following code:

import { Component, Prop, Vue } from 'vue-property-decorator'
import HeaderPrimary from '@/components/Header/HeaderPrimary.vue'
import query from '@/graphql/users.gql'

@Component({
	components: {           // Error from here
		HeaderPrimary,  // ...
	},                      // to here.
	apollo: {
		users: query,
	},
})
export default class TheHeader extends Vue {
	users: any = null
}

I'm receiving the following error:

Argument of type '{ components: { HeaderPrimary: {}; }; apollo: { users: DocumentNode; }; }' is not assignable to parameter of type 'VueClass<Vue>'.
  Object literal may only specify known properties, but 'components' does not exist in type 'VueClass<Vue>'. Did you mean to write 'component'?

When I remove the apollo part of the @Component, the error goes away.

The app still runs fine and queries correctly, but unfortunately I'm not sure how to get past this TypeScript error.

tqwewe avatar Dec 22 '18 11:12 tqwewe

I had the same type error problem and looked at the typings for the VueApolloComponentOptions. It seems the query should be either a DocumentNode or a function returning a DocumentNode, but for some reason, it errors on the DocumentNode alone.

Your error should be sorted out with

@Component({
	components: {           
		HeaderPrimary, 
	},        
	apollo: {
		users: () => query,
	},
})

Kresten avatar Jan 28 '19 16:01 Kresten

I have exactly the same issue and unfortunately @Kresten suggestion didn't work for me. Any help would be much appreciated :)

Source:

index.vue

import { Vue, Component } from 'vue-property-decorator';

import gqlTranslations from './translations.gql';
import Logo from '~/components/Logo.vue';

@Component({
  components: {
    Logo,
  },
  apollo: {
    translations: {
      query: gqlTranslations,
      variables() {
        return {
          namespace: 'index',
          language: 'en',
        };
      },
    },
  },
})
export default class IndexPage extends Vue {
  private translations = {};
}

translations.gql

query translations($namespace: String!, $language: String!) {
  translations(input: { namespace: $namespace, language: $language })
}

ZeD3v avatar Apr 11 '19 08:04 ZeD3v

any solution to this?

gdpaulmil avatar Jun 09 '19 00:06 gdpaulmil

@Acidic9 @jurgisrudaks @gdpaulmil

I suggest this is not gonna be happened if vue-apollo module is imported correct. If it's not loaded, it could be like as @Acidic9 said. like below

image

but if you import vue-apollo module somewhere on your codebase, it should be work. As you can see error has disapieared. image

joe-re avatar Jul 08 '19 19:07 joe-re

That doesn't work for me. I've imported vue-apollo as shown and in multiple other places. The only situation that works for a DocumentNode is assigning with a function:

import { SomeDocument } from 'documents'

apollo: {
  thing: () => SomeDocument
}

bbugh avatar Aug 05 '19 23:08 bbugh

@bbugh Can you share us whole of your example? This code is working for me..

<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import gqlTranslations from "./test.graphql";
import Logo from "~/components/Logo.vue";
import "vue-apollo";

@Component({
  components: {
    Logo
  },
  apollo: {
    translations: () => gqlTranslations
  }
})
export default class IndexPage extends Vue {
  private translations = {};
}
</script>

Also I think you can write it like this. Does this work for you?

@Component({
  components: {
    Logo
  },
  apollo: {
    translations: {
      query: () => gqlTranslations
    },
  },
})

joe-re avatar Aug 09 '19 18:08 joe-re

Using a function works but it's not ideal. When will this be fixed ?

gotenxds avatar Oct 18 '19 21:10 gotenxds

It will be fixed by using the composition function. I'm almost giving up fixing all of those typing issues, which is both frustrating and taking way too much of my time (still open to PRs :smile_cat: ).

Akryum avatar Oct 19 '19 23:10 Akryum

@Akryum

By mentioned about composition function, Do you mean Vue Composition API?

Could you help to explain how to use the composition function to fix this?

Is it like

setup() {
    const apollo = {};
    apollo.addSmartQuery('todoList', ...);

    // expose to template
    return {
      apollo
    }
  }

or like this?

setup() {
    const apollo = {
      todoList: {
         query: getTodoList
      }
    };

    // expose to template
    return {
      apollo
    }
  }

alexxiyang avatar Mar 30 '20 04:03 alexxiyang

See https://v4.apollo.vuejs.org/guide-composable/

Akryum avatar Mar 30 '20 10:03 Akryum

Just add "vue-apollo" in tsconfig.json :

{
  "compilerOptions": {
    "types": [..., "vue-apollo"]
  }
}

stphdenis avatar Apr 22 '20 21:04 stphdenis

@Akryum the purpose of the composition API for vue 2 is to let developers experiment the composition API in Vue 3. But it is not something to be used in production, as stated on the repo in bold:

We do not recommend using this package for production yet at this stage

So using the composition API in Vue 2 seems not to be a viable solution, is it ? I think there should be both:

  • a vue-apollo release for Vue 2 without using the composition API
  • optionally a vue-apollo release for Vue 3 using exclusively the composition API

Don't you think solutions built around the composition API for Vue 2 will be compromised at Vue 3 release ?

I should add the purpose of this issue is to solve a typescript error, but using the composition API at the moment imply dozens of new typescript errors, unsolvable for most of them since they are in the @vue/composition-api module

loicmarie avatar Jun 11 '20 14:06 loicmarie

thanks , i got it that how to use vue-apollo in typescript!

heavenkiller2018 avatar Jul 26 '20 08:07 heavenkiller2018

Just add "vue-apollo" in tsconfig.json :

{
  "compilerOptions": {
    "types": [..., "vue-apollo"]
  }
}

Worked for me. Thanks

toshoajibade avatar Aug 08 '20 01:08 toshoajibade

I always geht a typeerror as soon as I try to add variables in the query. Any solution? :)

Manubi avatar Aug 21 '20 12:08 Manubi

Maybe this will help someone. Vue2 + "vue-property-decorator" + vue-apollo It works for me:

<script lang="ts">
import { Component, Watch, Vue } from "vue-property-decorator";
import gql from "graphql-tag";
import { GET_COURSE } from "../../graphql/courses";`

@Component({
  components: {
    // other components
  },
  apollo: {
    teacherCourse: {
      query: GET_COURSE,
      result(resp) {
         // some logic
      },
      variables() {
        return {
          id: this.$route.params.slug,
        };
      },
    },
  },
})
export default class LessonsList extends Vue {
  teacherCourse: object = {};
  // some code
}

courses.ts

import gql from 'graphql-tag';
import 'vue-apollo';

export const GET_COURSE = gql`
  query($id: UUID!) {
    teacherCourse(input: { id: $id }) {
      name
      id
      chapters {
        id
        name
        courseID
        lessons {
          id
          name
          content
        }
      }
    }
  }
`;

And main.ts (just in case) if you want to see, how it is set up:

import Vue from 'vue';
import VueApollo from 'vue-apollo'
import App from './App.vue';
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'

// HTTP connection to the API
const httpLink = createHttpLink({
    // You should use an absolute URL here
    uri: '/graphql',
    credentials: 'include'
  })
  
  // Cache implementation
  const cache = new InMemoryCache()
  
  // Create the apollo client
  const apolloClient = new ApolloClient({
    link: httpLink,
    cache,
  })

  const apolloProvider = new VueApollo({
    defaultClient: apolloClient,
  })

  Vue.use(VueApollo);
  
  new Vue({
  //  other stuff
  apolloProvider,
  el: '#app',
  render: (h) => h(App),
});

Tassaczek avatar Oct 24 '21 14:10 Tassaczek