Graphql-code-generator: [Typescript-Resolvers] Required arguments with default values marked as optional

Created on 23 Oct 2019  路  3Comments  路  Source: dotansimha/graphql-code-generator

Describe the bug

When generating for a backend server, required arguments with default values are marked as optional in the generated types. I would expect a arguments with defaults to be optional on clients, but on the server these values will always be set since they will either have a default or would be explicitly set by the client request.

Seems identical to and earlier issue: https://github.com/dotansimha/graphql-code-generator/issues/2064

To Reproduce
Steps to reproduce the behavior:

Reproduced in the following sandbox. Look at incorrectTypedArg being given as an argument to the user query.

https://codesandbox.io/s/graphql-codegen-issue-template-bpun1

Expected behavior

I would expect incorrectTypedArg to be marked as non-optional in the generated types:

export type QueryUserArgs = {
  id: Scalars["ID"];
  incorrectTypedArg: Scalars["Int"];
};

Environment:

  • OS: Mac Catalina
  • @graphql-codegen/...: 1.8.2
  • NodeJS: 12.8.0

Most helpful comment

Hi @Tybot204 ,
The QueryUserArgs is defined as optional, but if you'll take a look at the resolver signature, you'll see that we override it to make it non-optional:

RequireFields<QueryUserArgs, 'id' | 'incorrectTypedArg'>

The reason is works this way, is because typescript plugin generates types as base types. From a client side perspective, a variable with default value is optional, but from a server side perspective, it's non-optional. We decided to keep the original Args type as-is, and change it during the creation of resolvers signature.

Use the resolvers signature on a high-level variable, and you won't need to add QueryUserArgs explicitly:

const resolvers: Resolvers = {
  Query: {
     user: (root, args, context, info) => {
       args.incorrectTypedArg // this is now non-optional, no need to specify `QueryUserArgs` explicitly
     }
  }
};

All 3 comments

Hi @Tybot204 ,
The QueryUserArgs is defined as optional, but if you'll take a look at the resolver signature, you'll see that we override it to make it non-optional:

RequireFields<QueryUserArgs, 'id' | 'incorrectTypedArg'>

The reason is works this way, is because typescript plugin generates types as base types. From a client side perspective, a variable with default value is optional, but from a server side perspective, it's non-optional. We decided to keep the original Args type as-is, and change it during the creation of resolvers signature.

Use the resolvers signature on a high-level variable, and you won't need to add QueryUserArgs explicitly:

const resolvers: Resolvers = {
  Query: {
     user: (root, args, context, info) => {
       args.incorrectTypedArg // this is now non-optional, no need to specify `QueryUserArgs` explicitly
     }
  }
};

Hi @dotansimha,

Should this also work for nested values?
Say we have something like this:

  input CorrectlyTypedInput {
    nestedIncorrectInput: Int = 10
  }
  type RootMutation {
    veryCoolMutation(input: CorrectlyTypedInput = {}): Boolean!
  }

The input argument is non-optional, but the nestedIncorrectInput is still optional, which doesn't make sense for the server. It's mitigated by optional chaining, but can be annoying for non-trivial stuff.

const RootMutation: RootMutationResolvers = {
  veryCoolMutation: async (_, {input}) => {
    return input.nestedIncorrectInput?.toString(10) === "1";
  }
}

I'm not 100% sure. @edgarnansen if it's still relevant and causes issues for you, can you please report it in a new issue?

Was this page helpful?
0 / 5 - 0 ratings