Graphql-code-generator: Accessing field types is very complicated in 1.0

Created on 20 Mar 2019  路  6Comments  路  Source: dotansimha/graphql-code-generator

New issue from https://github.com/dotansimha/graphql-code-generator/issues/713#issuecomment-474884827

In pre 1.0 I tend write a lot code like this:

https://github.com/epeli/graphql-codegen-issue/blob/pre-1.0/usage.tsx

I use the PostsQuery type in the top level component and pass parts of if it to smaller subcomponents. To make it easier I import the individual field types from the generated types. This is clean and simple.

But in 1.0 other types than the PostsQuery are gone and the field types are infered from the query type like this:

https://github.com/epeli/graphql-codegen-issue/blob/post-1.0/types.ts#L6450-L6495

From that it is really hard to extract the individual field types used in the query.

The only way I managed to do it was like this:

type ArrayType<T> = T extends Array<infer V> ? V : never;
type PostsTags = NonNullable<
    ArrayType<NonNullable<PostsQuery["posts"]>["edges"]>["node"]
>["tags"];

And this is a simple case. I'm having hard time migrating. Any better solutions?

Here's the full 1.0 port of the code:

https://github.com/epeli/graphql-codegen-issue/blob/post-1.0/usage.tsx#L28-L30

If you want to play with this:

git clone [email protected]:epeli/graphql-codegen-issue.git
cd graphql-codegen-issue
git checkout -t origin/post-1.0
npm ci

and open usage.tsx

Most helpful comment

I've been using fragments for types I need... it really made my code much easier and cleaner

All 6 comments

I've been using fragments for types I need... it really made my code much easier and cleaner

@epeli I recommend to use fragments, not only because of the codegen - it helps to make sure that you are getting all the fields that you need for your types, and it's very helpful if you are using client with cache (like Apollo Client).
The reason to use a single type is that fact that having more that one requires us to group it (with namespaces) and we are trying to avoid them. It also caused a lot of conflicts and mismatches.

You can create a custom type that refers to an internal type (using Type['field']).

I don't understand why you need to wrap your referring type with NonNullable - it should work without it. The following example works without any issues:

type Maybe<T> = T | null;

type T = {
  a?: Maybe<{
    b?: Maybe<{
      c?: Maybe<{
        d?: Maybe<{
          e?: string
        }>
      }[]>
    }>
  }>
}

type E = T['a']['b']['c'][0]['d']['e']; // access optional, nullable, and an internal array type.

const t: E = 'must-be-string';

Sorry, my example code was bad because it was missing tsconfig.json with the strict flag which I use in my application code. I've updated the examples now.

With tsconfig.json in place your example gives this error:

image

Hence the NonNullable wrapping.

But I looked more closely into the fragments workaround and it seems fairly workable solution:

https://github.com/epeli/graphql-codegen-issue/commit/3ca6b0244034d0af3f3c16c7e8c56dfc53666f03

It's bit limiting though compared to pre 1.0 because with it I have to design the fragments to match my components/functions. What if I have two components that use the query data differently?

@epeli you can create 2 fragments with different selection set (and they can be placed in the same file).
We are open for making the typings easier to use, do you have an idea? I can create a plugin that will create those inner-fields references that will also generate NonNullable for strict TS, but I afraid it might cause duplicate identifiers.

Interesting. Need to experiment more with fragments.

Sorry, I don't have any suggestions on how to make it easier to use ATM. Will let you known if I come up with something.

@epeli Closing for now, feel free to contact me or reopen if you think we can/should improve it :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SimenB picture SimenB  路  3Comments

zenVentzi picture zenVentzi  路  3Comments

jackhkmatthews picture jackhkmatthews  路  3Comments

mszczepanczyk picture mszczepanczyk  路  3Comments

iamdanthedev picture iamdanthedev  路  3Comments