vuejs / apollo

🚀 Apollo/GraphQL integration for VueJS
http://apollo.vuejs.org
MIT License
6.03k stars 523 forks source link

v3.0.0 regression: TypeScript mixins broken in v3.0.0, working fine in rc7 #847

Open bbugh opened 5 years ago

bbugh commented 5 years ago

Describe the bug

Hey @Akryum I know you how much you love TypeScript typing issues, so I just know you'll love this one! 🤪

When using TypeScript Vue component after upgrading vue-apollo v3.0.0-rc7 to v3.0.0, mixins no longer compile. Typed mixins can be done with vue-typed-mixins or the using the mixins helper from Vuetify. I confirmed this by switching back to rc7 on a clean repository folder, building (works fine), then another clean repo folder with v3.0.0 and receive this error:

ERROR in /Users/bbugh/somewhere/SomeComponent.vue
ERROR in /Users/bbugh/somewhere/SomeComponent.vue(25,46):
TS2769: No overload matches this call.
  The last overload gave the following error.
    Argument of type '{ name: string; components: { PageForm: { name: string; components: { DeleteButton: any; ItemFormHeader: any; ItemSelector: any; FormImageUploader: any; FormSaveButton: any; FormItemSelect: any; }; ... 6 more ...; apollo: { ...; }; }; }; computed: { ...; }; methods: { ...; }; }' is not assignable to parameter of type 'ComponentOptions<{ currentProject: any; } & { respondWith(resource: { id: string; }, errors?: any[], message?: string, routeOptions?: RespondWithOptions): void; pushReturnTo({ hash, fallback }: { hash: string | null; fallback?: string | undefined; }): void; } & Record<...> & { ...; } & Vue, ... 4 more ..., Record<.....'.
      Types of property 'components' are incompatible.
        Type '{ PageForm: { name: string; components: { DeleteButton: any; ItemFormHeader: any; ItemSelector: any; FormImageUploader: any; FormSaveButton: any; FormItemSelect: any; }; mixins: any[]; ... 5 more ...; apollo: { ...; }; }; }' is not assignable to type '{ [key: string]: VueConstructor<Vue> | FunctionalComponentOptions<any, PropsDefinition<any>> | ComponentOptions<never, any, any, any, any, Record<string, any>> | AsyncComponentPromise<any, any, any, any> | AsyncComponentFactory<...>; }'.
          Property 'PageForm' is incompatible with index signature.
            Type '{ name: string; components: { DeleteButton: any; ItemFormHeader: any; ItemSelector: any; FormImageUploader: any; FormSaveButton: any; FormItemSelect: any; }; mixins: any[]; props: { project: { ...; }; ... 4 more ...; preservePhoto: { ...; }; }; ... 4 more ...; apollo: { ...; }; }' is not assignable to type 'VueConstructor<Vue> | FunctionalComponentOptions<any, PropsDefinition<any>> | ComponentOptions<never, any, any, any, any, Record<string, any>> | AsyncComponentPromise<any, any, any, any> | AsyncComponentFactory<...>'.
              Type '{ name: string; components: { DeleteButton: any; ItemFormHeader: any; ItemSelector: any; FormImageUploader: any; FormSaveButton: any; FormItemSelect: any; }; mixins: any[]; props: { project: { ...; }; ... 4 more ...; preservePhoto: { ...; }; }; ... 4 more ...; apollo: { ...; }; }' is not assignable to type 'ComponentOptions<never, any, any, any, any, Record<string, any>>'.
                Types of property 'apollo' are incompatible.
                  Type '{ item: { query: typeof import("*.gql"); skip(): any; variables(): any; update({ item }: { item: any; }): any; }; item: { query: any; variables(): any; skip(): any; update({ item }: { item: any; }): any; }; tracking: any; schedules: typeof import("*.gql"); }' is not assignable to type 'VueApolloComponentOptions<never>'.
                    Type '{ item: { query: typeof import("*.gql"); skip(): any; variables(): any; update({ item }: { item: any; }): any; }; item: { query: any; variables(): any; skip(): any; update({ item }: { item: any; }): any; }; tracking: any; schedules: typeof import("*.gql"); }' is not assignable to type 'PrivateVueApolloComponentOptions'.
                      Property 'item' is incompatible with index signature.
                        Type '{ query: typeof import("*.gql"); skip(): any; variables(): any; update({ item }: { item: any; }): any; }' is not assignable to type 'string | boolean | DocumentNode | WatchLoading | ErrorHandler | VueApolloQueryDefinition<any, OperationVariables> | Partial<VueApolloQueryDefinition<any, OperationVariables>> | VueApolloSubscriptionDefinition<...> | { ...; } | (() => VueApolloQueryDefinition<...> | null) | undefined'.
                          Type '{ query: typeof import("*.gql"); skip(): any; variables(): any; update({ item }: { item: any; }): any; }' is not assignable to type '{ [key: string]: VueApolloSubscriptionDefinition<OperationVariables>; }'.
                            Property 'query' is incompatible with index signature.
                              Property 'query' is missing in type 'typeof import("*.gql")' but required in type 'VueApolloSubscriptionDefinition<OperationVariables>'.

ERROR in /Users/bbugh/somewhere/SomeComponent.vue
ERROR in /Users/bbugh/somewhere/SomeComponent.vue(39,35):
TS2339: Property 'params' does not exist on type 'ComputedOptions<any> | (() => any)'.
  Property 'params' does not exist on type 'ComputedOptions<any>'.

To Reproduce

Use mixins with v3.0.0. Here's an example component that builds fine with 3.0.0-rc7, but breaks when the only change is to upgrade to 3.0.0:

<script lang="ts">
import mixins from 'vue-typed-mixins'
import ProjectSubview from '...' // this is the mixin
import { itemCreateMutationOptions } from '...'

export default mixins(ProjectSubview).extend({
  name: 'SomeComponent',
  computed: {
    itemId () {
      return parseInt(this.$route.params.itemId)
    }
  },
  methods: {
    onSubmit (item: Item) {
      return this.$apollo
        // currentProject comes from ProjectSubview, breaks in v3.0.0
        .mutate(itemCreateMutationOptions(item, this.currentProject.id))
        .then(({ data: { itemCreate: { item, errors } } }) => {
          // respondWith comes from from ProjectSubview, breaks in v3.0.0
          this.respondWith(item, errors, 'Item created!', { hash: 'item' })
        })
    }
  }
})
</script>

Expected behavior

Mixins should work correctly in v3.0.0.

Versions

These are the versions as of the repository tag v3.0.0 (c36e334)

vue: vue@2.6.10 vue-apollo: vue-apollo@3.0.0 apollo-client: apollo-client@2.6.3

Additional context Add any other context about the problem here.

gperez-rms commented 4 years ago

Has this been resolved? I can't use the apollo mixin on my components without TS complaining

bbugh commented 4 years ago

It hasn't been for me. I had to roll back the upgrade to 3.0.0 and stuck with rc7, unfortunately.

jthomaschewski commented 4 years ago

This is probably related to the addition of *.graphql-typing in version 3.0.0-stable. It's also causing various other issues and unfortunately these kind of types can't be excluded in tsconfig.

The relevant error message is: Property 'query' is missing in type 'typeof import("*.gql")' And *.gql is typed in https://github.com/vuejs/vue-apollo/blob/dev/packages/vue-apollo/types/gql.d.ts as follows:

declare module '*.gql' {
  import { DocumentNode } from 'graphql'
  const content: DocumentNode
  export default content
}

"query" doesnt exist => type error.

Using an any type or generated types using graphql-code-generator would probably workaround this issue.

I did a PR which removes typings for *.gql and *.graphql from this library. This allows custom types which might be any or more sophisticated: https://github.com/vuejs/vue-apollo/pull/881 Unfortunately there is no response yet.