-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
resolve makeFragmentData
type problem by creating unmask Fragment utility type
#9708
base: master
Are you sure you want to change the base?
resolve makeFragmentData
type problem by creating unmask Fragment utility type
#9708
Conversation
🦋 Changeset detectedLatest commit: 015cefe The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
const documentNodeImport = `${useTypeImports ? 'import type' : 'import'} { ResultOf, DocumentTypeDecoration${ | ||
const documentNodeImport = `${useTypeImports ? 'import type' : 'import'} { DocumentTypeDecoration${ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this change, we don't use ResultOf
utility type in this file any more.
} & (F extends { " $fragmentRefs"?: { [K in string]: infer FRefs }; } | ||
? (FRefs extends any ? Flatten<FRefs> : never) : {} | ||
); | ||
export type UnmaskFragment<F> = UnionFieldToIntersection<Flatten<F>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UnmaskFragment
utility type consists of two utility types, Flatten
and UnionFieldToIntersection
.
Flatten
refers to ' $fragmentRefs'
properties and returns a new type by making the all sub-fragment flat recursively.
it returns a union type of fragments if the fragment includes multiple fragments in the same field. So we use UnionFieldToIntersection
to transform it to an intersection type of them.
I made a playground, so you will be able to see how they actually works.
type UnionToIntersectGroupByTypeName<U, V = U> = [V] extends [ | ||
{ __typename?: infer TypeName } | ||
] | ||
? TypeName extends any | ||
? UnionToIntersection<U extends { __typename?: TypeName } ? U : never> | ||
: never | ||
: never; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to make the union of fragment type into an intersection type of them if and only if they have same __typename
value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made something like type tests of makeFragmentData
.
Unfortunately, it seems there is no type checking in CI process. So there is no rational way to check the type of makeFragmentData
is correct.
If you know of a better way, please let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a small example of makeFragmentData
with nested fragment.
Actually it is not able to be typed with the previous implementation of makeFragmentData
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some field for tests of makeFragmentData
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of changes are made by running scripts.
I left comments to at the files I changes. You can just ignore other files for quick review.
>(data: FT, _fragment: F): FragmentType<F> { | ||
return data as FragmentType<F>; | ||
>(data: UnmaskFragment<FragmentType<F>>, _fragment: F): FragmentType<F> { | ||
return data as any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main update of this PR is here.
ResultOf<F>
does not accept any object if the fragment includes multiple fragments (I made an example #9702 ).
I made UnmaskFragment
utility type to make it able to accept valid data for the fragment.
a7b8032
to
fcd0129
Compare
you need to prepare clone and build the repository
makeFragmentData
type problem with creating unmask Fragment utility type
makeFragmentData
type problem with creating unmask Fragment utility typemakeFragmentData
type problem by creating unmask Fragment utility type
you need to prepare clone and build the repository
Can anyone help me to fix ci problem? https://github.com/dotansimha/graphql-code-generator/actions/runs/6524719251/job/17716636556?pr=9708 |
@saihaj Could you please provide some advice on how to approach this? |
it is not required since the previous commit
run `yarn build & yarn generate:examples`
gql function seems not to be used since dotansimha#9217 is completed
this mock data is what is not able to be typed with the previous `makeFragmentData` function. That is because `TweetsFragment` includes two different fragments
run `yarn examples:codegen`
the reason of this change is to escape the error of type error. refer to https://github.com/dotansimha/graphql-code-generator/actions/runs/6523101984/job/17713396917?pr=9708
fcd0129
to
015cefe
Compare
Hello, I wanted to both bump this pr so hopefully @beerose @n1ru4l can take a look. While this PR or another related get's merged I created this
Example query:
And used it like:
But it does not work, perhaps this |
@adriangalilea I'm not sure what kind of library you are using for |
You can try the
useFragment
function andUnmaskFragment
type with graphql-code-generator-unmask-fragment package until it will be merged.Description
Related #9702
also related to #9380
makeFragmentData
can't make a mock data with a fragment includes multiple fragments (see #9702 ).I created
UnmaskFragment
and apply it to the first argument of the function to solve the problem.Type of change
This might be a breaking change if you are using nested
makeFragmentData
to create a mock data for a nested fragment as like follows:Screenshots/Sandbox (if appropriate/relevant):
sandbox of testing the
UnmaskingFragment
utility typeHow Has This Been Tested?
makeFragmentData
at a sandbox1.1. clone https://github.com/tnyo43/graphql-code-generator-issue-fragment-conflict and move to the root of it.
1.2. run
pnpm run install & pnpm run generate
.1.3. open "./src/User.tsx" and check the
mockData
is not able to be typed without any type assertion.User_UserFragment
includes multiple fragment.2.1 clone this repository and checkout to this branch (tnyo43:update-make-fragment-data-args-type)
2.2 run
yarn install & yarn build
3.1. move to sandbox and update the dependency of "@graphql-codegen/client-preset" to refer to the local change (ex.
"@graphql-codegen/client-preset": "file:../graphql-code-generator/packages/presets/client"
).3.2. run
pnpm run install & pnpm run generate
.3.3. open "./src/User.tsx" and update
mockData
as like follows. You will see that we don't need any extra type assertion for making mock data!Test Environment:
@graphql-codegen/cli
: 4.0.1@graphql-typed-document-node/core
: 3.2.0,typescript
: 5.2.2Checklist:
Further comments
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...