-
-
Notifications
You must be signed in to change notification settings - Fork 530
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
Improve GraphQL TypedDocumentNode usage in the new MSW.js version #1881
Comments
Hey. This looks like a bug with the body type inference. Thanks for sharing this! A type test is clearly missing on our part. |
Glad to hear that it is just a bug. Thank you for your work! You guys rock! 🚀 |
@MatejBransky I can't reproduce this behavior myself, and I have working type inference for the One thing worth noting is that if you're using graphql.query(GetUser, () =>
HttpResponse.json({
__typename: 'User' as const,
// ... user properties, with inference
})
); |
@pleunv Could you please confirm that if you manually pass the query type as a type parameter, everything works as you expect it: graphql.query<GetUserQuery>(GetUser, () =>
HttpResponse.json({
__typename: 'User',
// ... user properties, with inference
})
); If so, that more or less confirms the same problem I'm seeing: when I call Unfortunately my TypeScript skills are right in that sweet spot where I am pretty sure I understand the problem, but I have absolutely no idea how to solve it. |
Edit: I tried the below locally using Looking at this: Lines 26 to 36 in e56f624
And given this: microsoft/TypeScript#14829 (comment)
The fix might be as simple as this: export type GraphQLRequestHandler = <
Query extends GraphQLQuery = GraphQLQuery,
Variables extends GraphQLVariables = GraphQLVariables,
>(
operationName:
| GraphQLHandlerNameSelector
| DocumentNode
| TypedDocumentNode<Query, Variables>,
resolver: GraphQLResponseResolver<Query & {}, Variables & {}>,
options?: RequestHandlerOptions,
) => GraphQLHandler Which should hopefully encourage TypeScript to infer |
Can confirm that works as well, yeah. You have two options when using
Both are a bit annoying, I went with the latter for now :) |
@aaronadamsCA, thanks for the suggestion! I don't think the function accept(name: 'john' | string): void {}
// All string inputs will be "coerces" to the shared
// type—which is just string. You won't get autocompletion
// on the "john" type of the "name".
accept('john')
accept('sarah')
function accept(name: 'john' | string & {}): void {}
// By using "& {}", we tell TS to differentiate between
// the "john" base type (string) and the "any other string"
// type. As a result, we get a proper autocompletion for "john":
accept('john')
// We also get any strings as "name" supported.
accept('sarah') It doesn't really affect the order in which the generic parameters are inferred, afafik. |
I've added a type test for Can it be that the Lines 17 to 24 in e56f624
This means if the GQL Code Gen was to change this type, like swapping the order of generics or changing the return type, MSW would stop inferring from it. This is also why the suggestion from @aaronadamsCA may work. If the |
Alas, just checked the I've also added Needs helpDoes anybody have a reproduction repository for this? Without it, I would have to close this issue as non-reproducible. |
I tried the TypeScript @kettanaito, I would expect #2018 to pass because your typed document node expected const GetUserQuery = {} as TypedDocumentNode<
{
user: {
- name: string
+ name: 'John'
}
},
{ userId: string } If that doesn't reproduce, I'll see what I can put together (I tried earlier today but the CodeSandbox starter seems to be broken, the dependencies won't install). |
@aaronadamsCA, I've just tried a narrower type for I think the only case when that won't happen is if the type of Lines 17 to 24 in e56f624
Can you please look at the type of your document node and post it here? What fields does it have? There must be some divergence that causes the inference to break. Once again, a reproduction repository would be best. |
I've created this repo: https://github.com/MatejBransky/graphql-example Try to complete the already existing mocked query handler in the file The "foobar" doesn't trigger any TS error and expected "state" field should be suggested but it's not. The suggested shape should be: HttpResponse.json({
data: {
info: {
state: 'something'
}
}
}) |
And here's another repro: https://stackblitz.com/edit/typescript-hr75ym?file=reproduction.ts |
@MatejBransky, thanks for providing the repo! If you open import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core' There are no type definitions for the pnpm i @graphql-typed-document-node/core
It reports |
@aaronadamsCA, I'm getting what looks like correct type validation in that sandbox as-is: Is the expected state different from this? |
@kettanaito Awesome! Thank you! I can close it I guess? |
@MatejBransky, glad it helped! Give me a moment, I think I finally understand the problem with the sandbox from @aaronadamsCA. Investigating... |
@aaronadamsCA, that looks like an issue but I can't figure out where it belongs. Sharing my thoughts. The
I can see now what you were talking about. This may be beyond my skill. Perhaps @Andarist can have a piece of advice here once he's got a minute. Here's a playground that distills this example to the minimum. |
I will close this issue because it needs no changes on MSW's side. What @andreawyss is experiencing is not related to |
Yep, you've got it, @kettanaito. Therefore it happens with every
I'm not entirely sure the solution involves preventing type widening (which I don't think is possible?), but rather in controlling type inference. There must be a way to tell TypeScript to infer the query type from |
@aaronadamsCA, to clarify, this part is working as you describe:
It infers your query and variable types and annotates the resolver's return type to match the query type. There are no issues with this. The issue is the inference here: HttpResponse.json<T>(body: T) What I don't believe there's a way for the |
I've created a new reproduction that's as short as possible: https://stackblitz.com/edit/msw-response-type-mismatch?file=index.ts I think this is the best illustration that there really is a bug here, because it can be worked around by explicitly passing the same type parameter that is already being inferred. You can see that in both cases the type parameters to I don't know, maybe it's a TypeScript issue. Edit: Ah, simultaneous posts. I understand what you're saying, but then I would expect the workaround to fail as well. You can see that the inferred type of |
@aaronadamsCA, may I please ask you to open a new issue about this? I would like to take a proper look at it. It's just not related to |
So just to clarify - does that mean that in MSW v1 was possible to infer the return type from the typed document node immediately without any |
The easiest way to enforce |
Ok, so the workaround/solution is in the comment of the related PR. Thanks @pleunv ! 🙏 |
Scope
Improves an existing behavior
Compatibility
Feature description
Hi, we have successfully used MSW.js v1 with generated GraphQL typed documents (see type notation in screenshots) so we have to just import the TypedDocumentNode document itself and the rest has been inferred. It was one of the selling points in our team.
But this behavior doesn't work in the latest version because we have to return type-agnostic
HttpResponse.json()
which can't know what the response type should be.Am I missing some new way to do it with the same comfort, or is this completely gone?
The text was updated successfully, but these errors were encountered: