graphql-typed-document-node icon indicating copy to clipboard operation
graphql-typed-document-node copied to clipboard

3.1.1 breaks type inference

Open aloker opened this issue 3 years ago • 12 comments

After I upgraded from 3.1.0 to 3.1.1 I got a lot of type errors in my project.

My setup:

  • graphql-core-generator with @graphql-codegen/typed-document-node 2.2.2
  • urql 2.0.6 with @urql/preact 2.0.3
  • graphql 16
  • typescript 4.5.4

Query:

query ExampleQuery($id: ID!) {
  user(id: $id) {
    id
  }
}

Generated document:

export type ExampleQueryResult = { user?: { __typename: 'User', id: string } | null | undefined };

export type ExampleQueryVariables = Exact<{
  id: Scalars['ID'];
}>;

export const ExampleQueryDocument = {
  kind: "Document",
  definitions: [
    {
      kind: "OperationDefinition",
      operation: "query",
      name: { kind: "Name", value: "ExampleQuery" },
      variableDefinitions: [
        {
          kind: "VariableDefinition",
          variable: { kind: "Variable", name: { kind: "Name", value: "id" } },
          type: {
            kind: "NonNullType",
            type: { kind: "NamedType", name: { kind: "Name", value: "ID" } },
          },
        },
      ],
      selectionSet: {
        kind: "SelectionSet",
        selections: [
          {
            kind: "Field",
            name: { kind: "Name", value: "user" },
            arguments: [
              {
                kind: "Argument",
                name: { kind: "Name", value: "id" },
                value: {
                  kind: "Variable",
                  name: { kind: "Name", value: "id" },
                },
              },
            ],
            selectionSet: {
              kind: "SelectionSet",
              selections: [
                { kind: "Field", name: { kind: "Name", value: "id" } },
              ],
            },
          },
        ],
      },
    },
  ],
} as unknown as TypedDocumentNode<ExampleQueryResult, ExampleQueryVariables>;

Component:

import { ExampleQueryDocument } from '$api';
import { useQuery } from '@urql/preact';

export function ExampleComponent() {
  const [{ data }] = useQuery({
    query: ExampleQueryDocument,
    variables: {
      id: '123',
    },
  });

  const t = data?.user?.id;

  return <div>{t}</div>;
}

With v3.1.0 image

image

After upgrade to v3.1.1 image

image

This seems to be caused by the removal of __resultType and __variablesType in https://github.com/dotansimha/graphql-typed-document-node/commit/6ee77c273422bea7df58f92607e54fe73eba673a#diff-9a4ceebe7c6f86856371906c3f061d3b56b7457022b05179884a113e7ced67e8

If I add the properties back using interface augmentation, it works again:

import { DocumentNode } from 'graphql';

declare module '@graphql-typed-document-node/core' {
  interface TypedDocumentNode<Result = { [key: string]: any }, Variables = { [key: string]: any }>
    extends DocumentNode {
    __resultType?: Result;
    __variablesType?: Variables;
  }
}

aloker avatar Jan 05 '22 08:01 aloker

Yep confirmed. I am experiencing the same issue.

My current setup:

@graphql-typed-document-node/core: 3.1.0 @graphql-codegen/typed-document-node: 2.2.0 @apollo/client: 3.5.6, graphql: 15.8.0 typescript: 4.5.4

When I upgrade to @graphql-typed-document-node/core to 3.1.1, then I lose all the types on data and variables

adnan-sheikh avatar Jan 06 '22 11:01 adnan-sheikh

Same for me when using the latest versions of all the packages. Fixed by using @adnan-sheikh pinned package versions.

kansson avatar Jan 09 '22 20:01 kansson

Glad I found this thread, I confirm @graphql-typed-document-node/core: 3.1.1 is breaking the inference, 3.1.0 is good.

stephane303 avatar Jan 25 '22 19:01 stephane303

Same here

lensbart avatar Feb 27 '22 22:02 lensbart

Seem to be experiencing this as well

marisbest2 avatar Mar 31 '22 21:03 marisbest2

Hi

So far, a "simple setup" with the latest versions of @apollo/client/@urql/preact and @graphql-typed-document-node/core does not reproduce the issue. This playground example is available (to use it properly, do install the required dependencies in the "Plugins" tabs - on the right)

I also tried to reproduce it without dependencies (with pure types) as follows, without success.

if any of you can share a Github/Codesandbox/Stackblitz that reproduces the issue (using the latest versions), it would be very helpful! 🙇🏼

charlypoly avatar Apr 18 '22 12:04 charlypoly

@charlypoly I recently updated @apollo/client and @graphql-typed-document-node/core.

No issues with the newer versions of both. Thanks 👍🏻

adnan-sheikh avatar Jun 02 '22 13:06 adnan-sheikh

Works here, too. 👍

lensbart avatar Jun 02 '22 15:06 lensbart

@adnan-sheikh @lensbart Thank you for your feedback!

charlypoly avatar Jun 02 '22 17:06 charlypoly

@charlypoly Can we close this?

n1ru4l avatar Aug 19 '22 05:08 n1ru4l

Yes!

cc @dotansimha

charlypoly avatar Aug 19 '22 09:08 charlypoly

resolution

I was experiencing the same issue where types were not inferred (see full details below). The problem turned out to be a subtlety in typescript module resolution. My relevant tsconfig bits and folder structure:

"baseUrl": ".",
"moduleResolution": "node",
package/myapp/
    pages/**
    components/**
    graphql/index.ts

import "graphql" with the above config / folder structure results in the source file graphql/index.ts being considered for loading BEFORE node_modules/graphql. This means all the types imported in other node_modules including graphql-typed-document-node were yielding incorrect results because my graphql/index.ts file does not re-export all of node_modules/graphql.

Two potentials solutions:

  1. Rename the graphql directory to not clash with a node_module identifier
  2. add the following to tsconfig.
    "paths": {
      "graphql": ["node_modules/graphql"],
    }

I went with (2) because I didn't want to rename all of the imports currently referencing graphql/index


Original post

Something potentially interesting to add... I have a monorepo with two packages that are displaying different behavior. One properly infers the Data type and the other does not. They do have different tsconfigs, but i've so far been unable to track down a config option that explains the difference in behavior.

One insight from the package in which inference does not work:

const a: TypedDocumentNode<{}, {}> = {} as unknown as DocumentNode; gives the following tsc error

Type 'DocumentNode' has no properties in common with type 'TypedDocumentNode<{}, {}>'

That seems like an odd error to me considering TypedDocumentNode extends DocumentNode.

EDIT:

Digging a bit deeper:

import type { DocumentNode } from 'graphql'; also behaves different in the two packages.

In the correct one, DocumentNode is a valid type exported by graphql. In the incorrect one, typescript doesn't think DocumentNode is exported.

Module '"graphql"' has no exported member 'DocumentNode'. (tsserver 2305)

When I "go-to-definition" they both lead to the same file on disk in node_modules/graphql/language/ast.

awinograd avatar Mar 09 '23 22:03 awinograd