dotansimha / graphql-code-generator

A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins.
https://the-guild.dev/graphql/codegen/
MIT License
10.84k stars 1.33k forks source link

'Types' is declared but its value is never read #4900

Open Fi1osof opened 4 years ago

Fi1osof commented 4 years ago

Describe the bug

When generate separated files for fragments, added import * as Types from './types'; in any case, ever Types does not using. Generated code: ```ts # Never use cause fragment does not have Maybe<> fields import * as Types from './types'; import { gql } from '@apollo/client'; export type TopicsConnectionTopicFragment = { __typename?: 'Resource', id: string, updatedAt: any, name: string, uri: string }; export const TopicsConnectionTopicFragmentDoc = gql` fragment topicsConnectionTopic on Resource { id updatedAt name uri } `; ``` **To Reproduce** Steps to reproduce the behavior: ```js function createQueriesMap(filesMap: any) { let documentsString = '' for (const contents of filesMap.values()) { documentsString += contents + '\n' } const definitions = parse(documentsString).definitions const queriesAndFragments = definitions.filter( ({ kind }) => kind === 'OperationDefinition' || kind === 'FragmentDefinition' ) as Array const queriesMap = new Map() queriesAndFragments.forEach((definition) => { if (definition.name && definition.loc) { const name = definition.name.value const oldText = queriesMap.get(name) if (!oldText) { queriesMap.set( name, documentsString.substring(definition.loc.start, definition.loc.end) ) } else { const newText = documentsString.substring( definition.loc.start, definition.loc.end ) if ( oldText.replace(/\r/g, '').trim() !== newText.replace(/\r/g, '').trim() ) { throw new Error(`duplicate definitions ${name}`) } } } }) return queriesMap } ```
  1. My GraphQL schema:
# Put your schema here
fragment topicsConnectionTopic on Resource {
  id
  updatedAt
  name
  uri
}
  1. My codegen conf config file:
const codegenConfig = {
  plugins: [
    {
      add: {
        content: prependText.join(''),
      },
    },
    'typescript-operations',
    'typescript-react-apollo',
  ],
  preset: 'near-operation-file',
  presetConfig: {
    extension: '.ts',
    baseTypesPath: './types.ts',
  },
  config: {
    withHOC: false,
    withHooks: true,
    withComponent: false,
    preResolveTypes: true,
    exportFragmentSpreadSubTypes: true,
  },
}

Expected behavior

Environment:

  • OS:
  • @graphql-codegen/...:
  • NodeJS:

Additional context

dotansimha commented 4 years ago

I assume this is something to do with isUsingTypes method. PRs are welcome :D

tim-field commented 2 years ago

Hi just wondering if the bug label could be added to this? I suspect this is preventing a fair few people from upgrading

pleunv commented 2 years ago

Just ran into this as well while trying to integrate graphql-code-generator. Anyone happen to have found a workaround for this, by any chance? 🙂

pleunv commented 2 years ago

What I can observe so far:

When using the near-operation-file preset, the generator appears to ignore the custom scalar types defined in the schema file for all the fields in the selection sets, and instead maps the custom types to any (or whichever type is set as defaultScalarType) rather than to Types.Scalars['MyCustomScalar']. The isUsingTypes() does correctly infer that the custom type is defined by the main schema, resulting in the code assuming that the Types import is necessary.

The scalar mapping is somehow correct in the variable types. We're for example getting:

import * as Types from '../../../../typings/_custom/api.generated';

export type GetEditUserFormQueryVariables = Types.Exact<{
  userId: Types.Scalars['GUID']; // Correct
}>;

export type GetEditUserFormQuery = {
  __typename: 'Query';
  extendedUser: {
    __typename: 'ExtendedUser';
    id: string; // Incorrect, should be Types.Scalars['GUID']
  } | null;
};

When you have a simple query without variables or a fragment file you end up with the Types import on top but nothing using it, resulting in the 'Types' is declared but its value is never read compilation error.

For reference, my config below. You'd expect the bottom custom scalar config to be unnecessary since it should resolve to the Types, but if not set it maps everything to any... Or am I doing something wrong here?

schema: schema.json
generates:
  src/typings/_custom/api.generated.d.ts:
    plugins:
      - typescript
    config:
      enumsAsTypes: true
      defaultScalarType: unknown
      scalars:
        DateTime: string
        DateTimeOffset: string
        Decimal: number
        GUID: string
  src/:
    documents: 'src/**/*.gql'
    preset: near-operation-file
    presetConfig:
      baseTypesPath: typings/_custom/api.generated.d.ts
    plugins:
      - typescript-operations
      - typed-document-node
    config:
      scalars:
        DateTime: string
        DateTimeOffset: string
        Decimal: number
        GUID: string
pleunv commented 2 years ago

Just ran into this as well while trying to integrate graphql-code-generator. Anyone happen to have found a workaround for this, by any chance? 🙂

The issue can be worked around by simply changing the ScalarsMap in my example above from

config:
  scalars:
    DateTime: string
    DateTimeOffset: string
    Decimal: number
    GUID: string

to

config:
  scalars:
    DateTime: Types.Scalars['DateTime']
    DateTimeOffset: Types.Scalars['DateTimeOffset']
    Decimal: Types.Scalars['Decimal']
    GUID: Types.Scalars['GUID']

This will use the import that's already in place and should work around the TS error in the first post.

aaronadamsCA commented 2 years ago

I also figured out another workaround. You can't do this:

config:
  scalars:
    CustomType: import("custom-type-lib").CustomType
generates:
  src/graphql.generated.d.ts:
    plugins:
      - typescript
  src/:
    preset: near-operation-file
    presetConfig:
      baseTypesPath: graphql.generated.d.ts
      extension: .graphql.generated.ts
    plugins:
      - typescript-operations

Instead you must currently do this:

- config:
-   scalars:
-     CustomType: import("custom-type-lib").CustomType
  generates:
    src/graphql.generated.d.ts:
      plugins:
        - typescript
+     config:
+       scalars:
+         CustomType: import("custom-type-lib").CustomType
    src/:
      preset: near-operation-file
      presetConfig:
        baseTypesPath: graphql.generated.d.ts
        extension: .graphql.generated.ts
      plugins:
        - typescript-operations
+     config:
+       scalars:
+         CustomType: Types.Scalars["CustomType"]
RomainDejean58 commented 1 year ago

Hi, is there any update on this issue? I am having the same problem but the work around did not resolve it. Here is my config:

const config: CodegenConfig = {
  overwrite: true,
  schema: './genned-schema.json',
  documents: [
    './projects/webapp-client/js/**/!(*.generated).{graphql,gql,js,jsx,ts,tsx}',
  ],
  generates: {
    'projects/webapp-client/js/globalTypes.generated.ts': {
      plugins: ['typescript'],
      config: {
        scalars: {
          Date: 'Types.Scalars["Date"]',
          JSON: 'Types.Scalars["JSON"]',
          BasicScalar: 'Types.Scalars["BasicScalar"]',
        },
      },
    },
    'projects/webapp-client/js/': {
      preset: 'near-operation-file',
      presetConfig: {
        extension: '.generated.tsx',
        baseTypesPath: 'globalTypes.generated.ts',
      },
      plugins: ['typescript-operations', 'typescript-react-apollo'],
      config: {
        scalars: {
          Date: 'Types.Scalars["Date"]',
          JSON: 'Types.Scalars["JSON"]',
          BasicScalar: 'Types.Scalars["BasicScalar"]',
        },
      },
    },
  },
};

I am still seeing an import of Types at the top of my Fragment files that is not being used.

sbahman commented 1 year ago

@RomainDejean58 I am facing the same issue and my config is very similar to yours, have you been able to resolve this?

paulius005 commented 10 months ago

👋 Just wanted to note that I am facing the same issue as well

gkim795 commented 7 months ago

Running into this as well - commenting to follow the issue.

maxsalven commented 6 months ago

As an unpleasant workaround to get tsc to pass:

...,
plugins: [
  "typescript-operations",
  "typed-document-node",
  {
    add: {
      placement: "append",
      content: [
        "// @ts-expect-error",
        "type Dummy = Types.Maybe",
      ],
    },
  },
],