typescriptvue.jsgraphqlgraphql-codegenurql

How to allow Urql (typescript) to accept Vue reactive variables for queries created with graphql-codegen


I'm building a Vue project with urql and graphql-codegen.

Urql has the ability to take Vue reactive variables when using useQuery() to enable useQuery to be reactive and update when the variables do.

But graphql-codegen is creating the type for the variables parameter to require scalars (ex. string) and so typescript is throwing an error when I try to use (for ex.) a Ref instead.

This is my codegen.ts:

import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'http://localhost:5001/graphql',
  documents: ['src/**/*.vue', 'src/**/*.ts'],
  ignoreNoDocuments: true, // for better experience with the watcher
  generates: {
    './src/gql/': {
      preset: 'client',
      config: {
        useTypeImports: true,
        scalars: {
          CustomDate: 'string',
          ObjectID: 'string',
        },
            },
      plugins: [],
    },
  },
};

export default config;

A sample variable type that's created looks like:

export type Scalars = {
  String: string;
  ObjectID: string;
};

export type GetItemQueryVariables = Exact<{
  _id: Scalars['ObjectID'];
}>;

And then a sample call might be:

const id = ref('123');

const queryResult = useQuery({
  query: queryGQL, // which is the graphql for the get item query
  variables: { _id: id }, // this line complains that type Ref<string is not assignable to type string
});

I can cast queryGQL to be something more generic so that it will take any variables, but that defeats the point.

Is there a setting on graphql-codegen to fix this? Or alternately, some way I could automatically patch the generated typescript definitions to make it work?


Solution

  • Use reactive to convert refs to properties:

    let r = ref(123)    // Ref<number>
    let a = { r }       // { r: Ref<number> }
    let b = reactive(a) // { r: number }
    

    Example:

    const { data } = useQuery({
      query,
      variables: reactive({
        orderBy: ArticlesOrderBy.ViewedAt,
        order: Order.Desc,
        first: 2,
        after  // Ref<string>
      })
    })