Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Union variants are not considered optional #383

Open
martinjlowm opened this issue Nov 5, 2023 · 9 comments
Open

Union variants are not considered optional #383

martinjlowm opened this issue Nov 5, 2023 · 9 comments

Comments

@martinjlowm
Copy link

martinjlowm commented Nov 5, 2023

I just came across a problem with using fragments and I noticed from the following code emitting logic that enum variants are not considered optional. Is there a particular reason why that is the case?

https://github.com/graphql-editor/graphql-zeus/blob/master/packages/graphql-zeus-core/TreeToTS/templates/valueTypes/index.ts#L16

Type-wise this would require all fragments to be provided into the selection criteria because the fragment key-literal signature is required.

I'd argue optionality (as in the following) would be the desired behavior.

(f) => `\t\t["...on ${getTypeName(f.type.fieldType)}"]?: ${VALUETYPES}["${getTypeName(f.type.fieldType)}"]`,
@chrishale
Copy link

I would really like this also, I've yet to come across a GraphQL server that specifically requires all union variants in a request, so this feels like an easy win for a single character change.

@aexol
Copy link
Collaborator

aexol commented Dec 17, 2023

I don't know TBH, but you are expecting that server can return all types of union so this is correct behavior. If we made it optional it doesnt make sense. What happens when server returns other Type that we dont have? Runtime Error?

@martinjlowm
Copy link
Author

Can you elaborate on the last part? Not sure I understand your first statement either. Surely, marking the fragment optional still allows you to express all variant types.

As a concrete example consider the following query (GitHub's API is a good one, seeing that they heavily use unions):

# Zeus (with this proposal patched)
["ProjectV2ItemContent"]: AliasType<{
  ["...on DraftIssue"]?: ValueTypes["DraftIssue"],
  ["...on Issue"]?: ValueTypes["Issue"],
  ["...on PullRequest"]?: ValueTypes["PullRequest"]
  __typename?: boolean | `@${string}`
}>;

With the current behavior, one would have to express the query with all fragments included as the following even if you are only interested in the Issue-variant.

content {
  __typename
  ...on Issue {
    body
  }
  ...on DraftIssue {
    body # don't care
  }
  ...on PullRequest {
    body # don't care
  } 
}

Whereas making the field optional, the equivalent query would be:

content {
  __typename
  ...on Issue {
    body
  }
}

@chrishale
Copy link

I have seen some GraphQL servers implement a ... on Error for when something goes wrong but I think it's far more typical that when you don't pass the union that you're asking to return that you'd get an empty object, or just the __typename in the example above.

@klonwar
Copy link

klonwar commented Aug 15, 2024

Having a lot of troubles because unions are not optional.

We have two environments: prod and dev. We removed one option (...on SomeDeprecatedOption) on dev stand backend and now we want to update prod without downtime.

But if we update BE with old FE deployed, all requests will fail with graphql error Unknown type "SomeDeprecatedOption"

And if we try to update FE first, removing this option from the selector, it fails on build time with TS error: Property '["...on SomeDeprecatedOption"]' is missing

So, I'm forced to find workarounds like disabling TS in order to upgrade


By the way, graphql requests with partial union options selected are still valid and execute correctly, so such strict TS disables some GraphQL functionality. Another use case: I may want to have several selectors for one union type. handling some parts of it in different places of the app. Right now, zeus doesn't make it possible. Such selectors will show "Property is missing" error:

export const FirstContentSelector = Selector('SomeStrapiDynamicZone')({
  '...on FirstUnionType': {
    title: true
  },
})

export const SecondContentSelector = Selector('SomeStrapiDynamicZone')({
  '...on SecondUnionType': {
    image: true
  },
})

@aexol
Copy link
Collaborator

aexol commented Aug 15, 2024

Good point, should it return null from backend on the type that is not included in the selection?

@klonwar
Copy link

klonwar commented Aug 16, 2024

As for graphql, it's just returns what you've selected, just like any other graphql query.

If all items selected are missing it returns empty objects
image

If item exitsts it returns just selected items
image
image

If only one item exists it returns only this item
image

@aexol
Copy link
Collaborator

aexol commented Aug 19, 2024

Thanks. I will do it today/tomorrow. Thanks for all the input

@aexol
Copy link
Collaborator

aexol commented Aug 23, 2024

done in 5.4.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants