Is your feature request related to a problem? Please describe.
Remove undefined type for nullable fields
Describe the solution you'd like
Guaranteed values are generated like this
userId: Int! --> userId: Scalars['Int']
Which I can essentially assign to any typescript variable of number type. That's good.
However if i have nullable field this happens
userId: Int --> userId?: Maybe<Scalars['Int']>
This I can only assign to typescript variables of type number | null | undefined , null because of Maybe operator, and undefined because of ?
This feels wrong to type all my variables with both undefined flag and nullable, because when will it ever be undefined? Close with explanation if this is this intentional?
Describe alternatives you've considered
I've looked into plugins but none seems to address the issue
This is not codegen specific thing. This is how GraphQL works. If you don't define a field in GraphQL, it is considered as null. So if it is defined as null, it is considered as null again.
If you don't define a field in GraphQL, it is considered as null.
Exactly. It should be null, not null or undefined
Also it seems to be a codegen specific issue, as codegen is the one generating types. In Graphql schema it states userId:Int . This means either it will return an Int or null, but never undefined. Then codegen should be generating appropriately
userId: Maybe
As @ardatan said, it depends on how you define your GraphQL schema.
We are using Maybe wrapper in order to mark fields as nullable, which means the values could be null | undefined. We are doing that because that's how Maybe is defined in graphql.js library, and we wish to make the generated code compatible. Returning undefined is allowed in GraphQL and treated as null.
This is how the resolver signature is defined:

And Maybe is defined here: https://github.com/graphql/graphql-js/blob/master/src/tsutils/Maybe.d.ts
But, as with many other plugins of the codegen, we do understand how customiation is important, so we added maybeValue configuration, see: https://graphql-code-generator.com/docs/plugins/typescript#maybevalue-string-default-value-t--null
@dotansimha I understand your rationale with embracing undefined. But then why doesn't codegen's default value of Maybe align with that of graphql's tsutils?
I see that adding ? introduces undefined to the union in the OP's example (userId?: Maybe<Scalars['Int']>), subsequently bringing alignment. But codegen can't rely on ? when given a type containing an array of Maybe values, for instance:
Schema:
input MyFilter {
values: [String]!
}
Codegen:
export type MyFilter {
values: Array<Maybe<Scalars['String']>> // Maybe = T | null
}
If I later attempt to do the following:
import Maybe from 'graphql/tsutils/Maybe';
const values: Maybe<string>[] = ['hello', null, 'world', undefined]; // Maybe = T | null | undefined
const filter: MyFilter = { values }; // 馃挜(string | null | undefined)[] is not assignable to type (string | null)[]
I'll change the maybeValue config for now. However, would it make sense to default codegen's Maybe to T | null | undefined and not bother with optional properties ?.
You are right, but I suspect it might cause a breaking change. I think adding avoidOptionals: true might solve that for you?
maybeValue: T | null | undefined is enough, but avoidOptionals: true is the icing on the cake 馃槂
generates:
src/__generated__/graphql.tsx:
plugins:
- "typescript"
config:
maybeValue: T | null | undefined
avoidOptionals: true
Thanks for such an incredible tool btw 馃檹馃徑
Most helpful comment
maybeValue: T | null | undefinedis enough, butavoidOptionals: trueis the icing on the cake 馃槂Thanks for such an incredible tool btw 馃檹馃徑