dotansimha / graphql-typed-document-node

An improved version of `DocumentNode` for seamless TypeScript integration for GraphQL.
https://the-guild.dev/blog/typed-document-node
MIT License
385 stars 20 forks source link

Failed to compile in React Typescript with graphql-typed-document-node #131

Open devfromfinland opened 2 years ago

devfromfinland commented 2 years ago

Hi, I'm trying out your library. The example works fine for me, but when I apply it to my app, it failed to compile.

I have generated the types from backend schema and frontend operations. The file looks like this

import { GraphQLResolveInfo } from 'graphql';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
export type RequireFields<T, K extends keyof T> = { [X in Exclude<keyof T, K>]?: T[X] } & { [P in K]-?: NonNullable<T[P]> };

... all types

export const AllChannelsDocument = {...} as unknown as DocumentNode<AllChannelsQuery, AllChannelsQueryVariables>;

My query:

export const ALL_CHANNELS = gql`
  query allChannels {
    allChannels {
      id
      name
    }
  }
`;

My functional component:

import { AllChannelsDocument } from './generated-type'
import { ALL_CHANNELS } from './operations.ts'

function ChannelList(): JSX.Element {
  const test = useQuery(AllChannelsDocument);
  return (
    ...
  )
}

If I use useQuery(ALL_CHANNELS), it works but without type. If I use useQuery(AllChannelsDocument), I can see the type showing, but it failed to run the React App.

Here is the error message

Failed to compile.

../generated-type.ts 6:7
Module parse failed: Unexpected token (6:7)
File was processed with these loaders:
 * ./node_modules/react-scripts/node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
You may need an additional loader to handle the result of these loaders.
| import { GraphQLResolveInfo } from 'graphql';
| import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
> export type Maybe<T> = T | null;
| export type InputMaybe<T> = Maybe<T>;
| export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };

I have searched stackoverflow and found that I should downgrade react-scripts to 4.0.1. I did but it doesn't help resolving the issue.

Package versions in root (monorepo)

"dependencies": {
    "graphql": "^15.8.0",
    "typescript": "^4.5.2"
},
"devDependencies": {
    "@graphql-codegen/cli": "^2.3.1",
    "@graphql-codegen/introspection": "2.1.1",
    "@graphql-codegen/typed-document-node": "^2.2.2",
    "@graphql-codegen/typescript": "2.4.2",
    "@graphql-codegen/typescript-operations": "2.2.2",
    "@types/node": "^17.0.8"
}

Package versions in React App

"dependencies": {
    "@apollo/client": "^3.5.6",
    "@testing-library/jest-dom": "^5.16.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.1",
    "shared": "*",
    "styled-components": "^5.3.3",
    "web-vitals": "^1.1.2"
 }

I couldn't find any requirement regarding compileOptions for your library to work with React. I wonder what is the cause of this issue? (btw, I had to downgrade graphql to v15 for it to work with your example)

devfromfinland commented 2 years ago

I believe the issue is in the generated document.

If I use useQuery(ALL_CHANNELS), it works but without type. If I use useQuery(AllChannelsDocument), I can see the type showing, but it failed to run the React App. if I use useQuery<AllChannelsQuery, AllChannelsQueryVariables>(ALL_CHANNELS), it works with type. The types 'AllChannelsQuery', 'AllChannelsQueryVariables' are generated from codegen using your library

There might be something wrong with the generated AllChannelsDocument vs React/TS Compiler?

aloker commented 2 years ago

Maybe related to https://github.com/dotansimha/graphql-typed-document-node/issues/130

devfromfinland commented 2 years ago

I have updated the example apollo-client-3 and added a quick create-react-app to demonstrate the build error when adding useQuery(RatesDocument, { ... }) into the App.tsx here: https://github.com/devfromfinland/graphql-typed-document-node/tree/master/examples/apollo-client-3

soosap commented 1 year ago

Hi @devfromfinland, did you find a solution to this problem? Already struggling for quite some time with this.

djkato commented 1 year ago

Hello, this issue still persists with 3.2.0, but pinning to 3.1.0 solves it for me. I am using Astrojs + svelte, and other recommended things from urql typescript integration guide.

trm217 commented 1 year ago

Same issue is ocuring in Next.js v12 when using it together with the lastest @apollo/client release

iandoe commented 1 year ago

Facing the same issue here using URQL together with Astro v3:

This is not typed:

import { GetProductsDocument } from "../graphql/types"
const products = await urql.query(GetProductsDocument, { first: 10 }) // this is not typed

This is typed correctly:

import { GetProductsDocument } from "../graphql/types"
import type {
  GetProductsQuery,
  GetProductsQueryVariables,
} from "../graphql/types"

const products = await urql.query<GetProductsQuery, GetProductsQueryVariables>(
  GetProductsDocument,
  { first: 10 },
)

package.json

  "dependencies": {
    "@astrojs/cloudflare": "^7.0.1",
    "@astrojs/tailwind": "^5.0.0",
    "@urql/core": "^4.1.2",
    "astro": "^3.0.8",
    "autoprefixer": "^10.4.15",
    "tailwindcss": "^3.3.3",
    "zod": "^3.22.2"
  },
  "devDependencies": {
    "@graphql-codegen/cli": "5.0.0",
    "@graphql-codegen/typed-document-node": "^5.0.1",
    "@graphql-codegen/typescript": "4.0.1",
    "@graphql-codegen/typescript-operations": "^4.0.1",
    "@graphql-typed-document-node/core": "^3.2.0",
    "prettier": "^3.0.3",
    "prettier-plugin-astro": "^0.12.0",
    "prettier-plugin-tailwindcss": "^0.5.4",
    "wrangler": "^3.7.0"
  }

codegen.ts:

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

const config: CodegenConfig = {
  overwrite: true,
  schema: "./schema.json",
  documents: "src/graphql/**/*.gql",
  generates: {
    "src/graphql/types.ts": {
      plugins: ["typescript", "typescript-operations", "typed-document-node"],
      config: {
        useTypeImports: true,
      },
    },
  },
}

export default config
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';

// ...

export type GetProductsQueryVariables = Exact<{
  first: Scalars['Int']['input'];
}>;

export type GetProductsQuery = { __typename?: 'QueryRoot', products: { __typename?: 'ProductConnection', edges: Array<{ __typename?: 'ProductEdge', node: { __typename?: 'Product', id: string, title: string, handle: string, images: { __typename?: 'ImageConnection', nodes: Array<{ __typename?: 'Image', url: any, width?: number | null, height?: number | null, altText?: string | null }> }, variants: { __typename?: 'ProductVariantConnection', nodes: Array<{ __typename?: 'ProductVariant', id: string, title: string, availableForSale: boolean, price: { __typename?: 'MoneyV2', amount: any, currencyCode: CurrencyCode } }> }, featuredImage?: { __typename?: 'Image', url: any, width?: number | null, height?: number | null, altText?: string | null } | null } }> } };

export const GetProductsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"getProducts"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"products"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"images"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"width"}},{"kind":"Field","name":{"kind":"Name","value":"height"}},{"kind":"Field","name":{"kind":"Name","value":"altText"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"variants"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"availableForSale"}},{"kind":"Field","name":{"kind":"Name","value":"price"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"amount"}},{"kind":"Field","name":{"kind":"Name","value":"currencyCode"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"featuredImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"width"}},{"kind":"Field","name":{"kind":"Name","value":"height"}},{"kind":"Field","name":{"kind":"Name","value":"altText"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode<GetProductsQuery, GetProductsQueryVariables>;