Given this GraphQL type:
type Profile {
avatarUrl: String
displayName: String!
email: String!
}
TypeScript codegen generates this:
export interface users_docs_profile {
avatarUrl: string | null;
displayName: string;
email: string;
}
While this is correct from GraphQL perspective, I would prefer it generates avatarUrl as avatarUrl?: string instead. Current state makes it hard to assign GraphQL query result to my application's defined model, unless I use hacks like any (I use TypeScript strict checks).
In my TypeScript application, avatarUrl is defined as optional property and I can just ignore it when it is not used (manually assigning null is so tedious and not intuitive):
export interface Profile {
email: string;
displayName: string;
avatarUrl?: string;
}
If there is a need to maintain string | null for correctness from GraphQL perspective, at least provide CLI option to choose ?: instead of | null.
Thanks for reading this feature request & hope it will be considered.
Optionals are undefined and undefined !== null. There is a semantic difference between a field not being requested and thus not present (undefined) and it being requested but not set (null). Why can't your Profile be:
export interface Profile {
email: string;
displayName: string;
avatarUrl?: string | null;
}
then you don't have to manually assign anything or use hacks.
Hmm.. that make sense. Appreciate you taking the time to suggest this. Thanks @danilobuerger!
I commented on a similar issue but wanted to bring this up here as well.
I also think that you should be able to generate TypeScript models that use undefined instead of null from your client-side queries.
This comment explains why the null vs. undefined distinction is important when dealing with a GraphQL server. While I totally understand what they’re saying, I simply don’t think the distinction is meaningful when you’re specifically generating TypeScript model from queries.
From the comment linked to above:
nullmeans that the field requested is not available (either due to being non-existent or from an error) whileundefined(or absent from response) means that the field was not requested.
This is true, but since we’re generating our TypeScript models’ interfaces from our actual queries, the interfaces would never include a field that was not requested. As such, the distinction between “non-existent” and “not-requested” is not valuable.
In the scenario where you did request a field but your GraphQL resolver throws error for that field, it would be returned as null unless it has a ! suffix like name: String!.
So, even if your TS models are generated from the actual queries that include all fields, the values can still be null unless they are defined with a ! suffix.
I understand that there are valid reasons why the server may return a null value for a field. I am simply saying that I would prefer to have those fields show up as name?: string; instead of name: string | null in my Apollo-generated client-side TypeScript models.
I think it is perfectly fine to convert null to undefined when building a TypeScript application, since as I described above, the value in being able to differentiate between the two (fields with a null value vs. fields that were not requested by the query) doesn’t apply when you’re generating type-safe models _from_ your queries.
Its being generated as name?: string | null not name: string | null at the moment .
My server-side type is nullable – name: String – looking something like this in my schema:
{
"name": "name",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
In the generated TypeScript model, it looks like this:
interface Model {
name: string | null;
}
I want it to look like this instead:
interface Model {
name?: string;
}
Disregard my last comment, it just applies to optional inputs.
Anyway there is no point of writing in this closed issue, lets discuss in #622
Most helpful comment
I commented on a similar issue but wanted to bring this up here as well.
I also think that you should be able to generate TypeScript models that use
undefinedinstead ofnullfrom your client-side queries.This comment explains why the
nullvs.undefineddistinction is important when dealing with a GraphQL server. While I totally understand what they’re saying, I simply don’t think the distinction is meaningful when you’re specifically generating TypeScript model from queries.From the comment linked to above:
This is true, but since we’re generating our TypeScript models’ interfaces from our actual queries, the interfaces would never include a field that was not requested. As such, the distinction between “non-existent” and “not-requested” is not valuable.