Missing/incomplete mutate function variables types
rtrembecky opened this issue ยท 12 comments
Hi, I started using graphql-let
yesterday as a replacement for GraphQL Code Generator. Today I noticed a weird issue with types not being as strong as I'd like.
Maybe I remember wrong, but while using GraphQL Code Generator, I think I had variables of the mutate function typed and VSCode provided autocomplete when writing them. Here is an example of what I mean:
import { useChangeTickerMutation } from './tickersMutations.graphql'
const Example: FC = () => {
const [changeTicker] = useChangeTickerMutation({ variables: { } })
// ^ autocomplete/typecheck works here
const sendUpdate = () => changeTicker({ variables: { } })
// ^ autocomplete/typecheck doesn't work here (`variables` are `any`)
...
}
I tracked this to the tickersMutations.graphql.d.ts
file:
export declare function useChangeTickerMutation(baseOptions?: Apollo.MutationHookOptions<ChangeTickerMutation, ChangeTickerMutationVariables>): Apollo.MutationTuple<ChangeTickerMutation, any>;
I believe there should be Apollo.MutationTuple<ChangeTickerMutation, ChangeTickerMutationVariables>
in the end.
Hi @rtrembecky. It's weird and similar to #478 (comment). Could you change the skipLibCheck
, or moduleResolution
as the issuer mentioned?
To a future PRer: we need to figure out when the part of the generated types becomes any
. We probably have to overwrite the user's tsconfig by here. A test case for the issue seems difficult, so not necessary. Thank you for your help.
Could you change the
skipLibCheck
, ormoduleResolution
as the issuer mentioned?
My tsconfig.json
had "skipLibCheck": true
and "moduleResolution": "node"
. I confirm changing skipLibCheck
to false
has no effect on generated types.
Furthermore, I tried to set moduleResolution: "classic"
just to see what happens. The hook type became substantionally worse:
export declare function useChangeTickerMutation(baseOptions?: Apollo.MutationHookOptions<ChangeTickerMutation, ChangeTickerMutationVariables>): any;
note: I needed to remove the file in order to regenerate it, otherwise graphql-let
said the cache is fresh. However, this is probably expected.
I took a bit of a dive into your codebase, it seems there are no tests/examples for mutations. Luckily, I think I found the same problems for queries. E.g. in https://github.com/piglovesyou/graphql-let/blob/main/src/__snapshots__/gen.test.ts.snap#L58-L59:
export declare function useViewerQuery(baseOptions?: Apollo.QueryHookOptions<ViewerQuery, ViewerQueryVariables>): Apollo.QueryResult<ViewerQuery, any>;
export declare function useViewerLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ViewerQuery, ViewerQueryVariables>): Apollo.QueryTuple<ViewerQuery, any>;
Both of these should have ViewerQueryVariables
instead of any
as a second generic type argument to Apollo.QueryResult/QueryTuple
respectively.
3 hours of investigation later, back again. Found out the culprit. I need to get back to my work, I hope somebody can take it from here ๐
Reproducible example
let's have a simplified a.tsx
file:
import * as Apollo from '@apollo/client'
import { gql } from '@apollo/client'
import * as Types from '../../../node_modules/@types/graphql-let/__generated__/__types__'
const MyDocument = gql``
type MyQuery = { a: string }
type MyType = { b: string }
type MyVariables = MyType
export function useMy() {
return Apollo.useLazyQuery<MyQuery, MyVariables>(MyDocument, {})
}
type BadVariables = Types.Exact<{}>
export function useBad() {
return Apollo.useLazyQuery<MyQuery, BadVariables>(MyDocument, {})
}
I run this command to simulate what's done by graphql-let
:
yarn tsc a.tsx --skipLibCheck --declaration --emitDeclarationOnly
This is the a.d.ts
output:
import * as Apollo from '@apollo/client';
declare type MyQuery = {
a: string;
};
declare type MyType = {
b: string;
};
export declare function useMy(): Apollo.QueryTuple<MyQuery, MyType>;
export declare function useBad(): Apollo.QueryTuple<MyQuery, any>;
export {};
and there's actually an error in the console:
a.tsx:4:24 - error TS2307: Cannot find module '../../../node_modules/@types/graphql-let/__generated__/__types__' or its corresponding type declarations.
This Types
import needs to be correct during the typescript compilation because MyVariables
is resolved. But the import path is correct only after ending up in the final generated .d.ts
. What I mean - the correct import for compilation (in my case) would be '../../../../../../node_modules/@types/graphql-let/__generated__/__types__'
.
Fixing the import fixes the compilation and fixes the generated types.
I really appreciate your effort, @rtrembecky; yours is huge progress. I pushed a reproduction branch, which fails in this line. Now I understand how optimistic I was.
Problem: v0.18.0 lacks important types generated from graphql-let/__generated__/__types__
, just as @rtrembecky pointed out, because intermediate .tsx
es have incomplete import paths.
Solution: .tsx
es have to have the correct import paths, first. Next, graphql-let distributes .d.ts
es to the different directories, which breaks import paths again, and then graphql-let has to fix them again. This probably is an inefficient, quickest way for now.
A side talk. These all come from "distributing .d.ts
es to the different directory structure". I had thought we could import them as a module path like import "graphql-let/__generated__/__types__"
inside of .tsx
es and .d.ts
es, but I confirmed it throws an error in Create React App example. I don't want users to add a "paths": { "...": "..." }
option to their tsconfig.json either. I'm out of ideas for simpler solutions.
I published graphql-let@0.18.1-beta.0
, which must have fixed this issue. I'm happy if you give it a try.
Just tried it, works as expected ๐ Thanks for a prompt fix.
@rtrembecky Great, thanks for taking your time. I'll publish v0.18.1 soon.
FYI if you are getting duplicate type errors after updating to 0.18.1
, it may be because your using typescript-resolvers
and have enum values in your config under mappers
.
I'm not sure if this was previously intended to work, but the fix is to move them to the (presumably correct) enumValue
option (https://www.graphql-code-generator.com/docs/plugins/typescript)
Thank you for leaving such an important tip. Let me try and put it in the FAQ section later. If you happen to prepare a PR, I'll merge it.