graphql-code-generator: `Maybe` is inlined to include `undefined` in `typescript-operations` version 2.1.5

Describe the bug

When using the preResolveTypes option, Maybe types now include undefined in their union starting in version 2.1.5, regardless of any avoidOptionals options.

To Reproduce Steps to reproduce the behavior: https://codesandbox.io/s/amazing-montalcini-kuf9p?file=/codegen.yml Code Sandbox isn’t inlining Maybes for some reason right now. Maybe the dependencies aren’t updating correctly.

  1. My GraphQL schema:
type Query {
    user(id: ID!): User!
}

type User {
    id: ID!
    username: String!
    email: String
}
  1. My GraphQL operations:
# Put your operations here
query user {
    user(id: 1) {
        id
        username
        email
    }
}
  1. My codegen.yml config file:
schema: schema.graphql
documents: document.graphql
generates:
  types.ts:
    plugins:
      - typescript
      - typescript-operations
    config:
      avoidOptionals: true
      preResolveTypes: true

Expected behavior

The codesandbox isn’t inlining maybes for some reason. An example change for an operation. Maybe is being inlined as T | null | undefined even though avoidOptionals is true.

-export type CypressCreateOrgMutation = { newAccount: Maybe<{ __typename: 'Account', id: string }> };
+export type CypressCreateOrgMutation = { newAccount: { __typename: 'Account', id: string } | null | undefined };

Environment:

    "@graphql-codegen/add": "^2.0.2",
    "@graphql-codegen/cli": "2.2.0",
    "@graphql-codegen/plugin-helpers": "^2.1.1",
    "@graphql-codegen/typescript": "^2.2.2",
    "@graphql-codegen/typescript-operations": "^2.1.5",
    "@graphql-codegen/typescript-resolvers": "^1.19.1",
    "@graphql-codegen/visitor-plugin-common": "^2.2.1",

Additional context Probably related to this commit: https://github.com/dotansimha/graphql-code-generator/commit/25cd11d01ec55d5c6a2a83ebd501abdd1ed2f248

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 17
  • Comments: 25 (4 by maintainers)

Most upvoted comments

After today’s update, nullable fields of objects are generated as T | null | undefined instead of T | null.

I haven’t maybeValue configured, but when I set it to T | null (which is the default), nullable fields are generated correctly. It is strange that setting default value explicitly changes the behavior.

@gilgardosh This is still incorrect if you use custom maybeValue In my codegen.yml maybeValue is T | undefined, so I shouldn’t have | null in my types with preResolveTypes: true

I created #7104, which uses maybeValue: "T | null" as default. so no need to explicitly set maybeValue. Please let me know if this works for you.

I upgraded to the latest version and after generating types I had 100+ type errors in my large TypeScript project (strict mode) due to the inclusion of | undefined in the maybe type.

In my config script, like others have mentioned, I added maybeValue: "T | null" (JS format, in .yml you can leave out the quotes) based on these docs, then all the type errors went away and normal behavior restored 👍

maybeValue is begin used on typescript-operations. If preResolveTypes: false, optional types are wrapped with Maybe, which is declared on typescript plugin as maybeValue. But if preResolveTypes: true, then Maybe is not used at all, and types are becoming nullable and undefinedable (depends on avoidOptionals config).

@lanwin is right regarding the current implementation referring only the avoidOptionals boolean config, it’s fixed here

Keeping open until we’ll fully resolve this one. maybeValue should be applied and interpolated also with preResolveTypes: true. @gilgardosh can you please try to solve that?

I agree with @gilgardosh. Regardless of preResolveTypes or using Maybe<>, typescript-operations should use the maybeValue. The default value is T | null, not T | null | undefined.

This is also what I expect. The current version breaks our code.

I also found that avoidOptionals behaves different when used with sub object instead of boolean. The following example you could try out at https://www.graphql-code-generator.com/ (v2.2.0).

Schema

schema {  query: Query }
type Query { username: String }

Operations

{ username }

codegen.yaml - boolean

generates:
  types.ts:
    plugins:
      - typescript-operations            
    config:
      preResolveTypes: true
      avoidOptionals: true

Output:

export type Unnamed_1_Query = { __typename?: 'Query', username: string | null };

codegen.yaml - subobject

generates:
  types.ts:
    plugins:
      - typescript-operations            
    config:
      preResolveTypes: true
      avoidOptionals:
        field: true
        inputValue: true
        object: true
        defaultValue: true

Output:

export type Unnamed_1_Query = { __typename?: 'Query', username: string | null | undefined };

I would expect this should output exact the same result? Shouldn’t it?

@n1ru4l sorry for the slow response! This fixes the problem for me.

I agree with @gilgardosh. Regardless of preResolveTypes or using Maybe<>, typescript-operations should use the maybeValue. The default value is T | null, not T | null | undefined.

This is also what I expect. The current version breaks our code.

I agree this makes sense to interpolate the maybeValue when preResolveTypes is used. @gilgardosh is working on a fix 😃

I agree with @gilgardosh. Regardless of preResolveTypes or using Maybe<>, typescript-operations should use the maybeValue. The default value is T | null, not T | null | undefined.

Hi @oceandrama , in this case, since preResolveTypes is used, no maybe should be used in the generated types (neither the original nor the custom maybeValue)