dotansimha / graphql-code-generator

A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins.
https://the-guild.dev/graphql/codegen/
MIT License
10.84k stars 1.33k forks source link

[TypeScript Resolvers] Resolvers returned data type cannot be introspected #1103

Closed itscarlosrufo closed 5 years ago

itscarlosrufo commented 5 years ago

Describe the bug Cannot introspect resolvers returned data

To Reproduce Steps to reproduce the behavior:

Clone repository: git clone -b graphql-ts https://github.com/swcarlosrj/SpaceX-API.git Install deps & start server: yarn && yarn start Generate types: yarn generate Introspect src/schema/capsule/resolvers.ts resolvers returned data

Expected behavior This would be the desired behaviour, it's not even real because I've hardcoded QueryResolvers.CapsulesResolver from CapsulesResolver<...> = (Resolver<R, Parent, Context, CapsulesArgs> to CapsulesResolver<...> = Promise<Capsule[]>

I believe that it's a TypeScript thing but it'd be incredible if we could have that feature using QueryResolvers.Resolvers as here, does it's even possible?

Environment: OS: macOS Mojave 10.14.2 (18C54) Codegen: 0.15.2 Node: 10.10.0

Additional context It looks like that when you check the returned data type, it's well formed (in this case Capsule[]) but I cannot see in VSCode the fields of my type/interface as here

kamilkisiela commented 5 years ago

So what you want to have is a Return Type of a resolver?

Turning that:

namespace QueryResolvers {
  export type CapsuleResolver = Resolver<R,...>;
}

into:

namespace QueryResolvers {
  export type CapsuleResolver = Resolver<R,...>;

  export type CapsuleResult = Capsule;
}

Right?

itscarlosrufo commented 5 years ago

@kamilkisiela yep although not sure about how it'd should be the written in order to have the ability to introspect the resolver's returned data only using the QueryResolvers.Resolvers. That'd be the ideal case IMO but It could be added manually too!

Resuming, doing this, be able to do this (withouth adding QueryResolvers.CapsulesResolver)

kamilkisiela commented 5 years ago

@swcarlosrj

introspect the resolver's returned data only using the QueryResolvers.Resolvers

What do you mean by that, to return data of some shape in the resolver use that shape in a child resolver? Treat TypeScript as the source of truth and not the GraphQL Schema?

itscarlosrufo commented 5 years ago

What I meant is having already the returned data type of the resolver (in this case, Capsule), it'd be great to be able to introspected it, just in case that if I'd want to modify any field without going to the docs.

Actually it's not possible as you can see here, although looking at the returned data type Resolver<Capsule, {}, MyContext, QueryResolvers.CapsuleArgs> where Resolver<Capsule> is Promise<Result> | Result Idk why it doesn't work as Promise<Capsule> does

kamilkisiela commented 5 years ago

@swcarlosrj QueryResolvers.CapsuleResolvers is a type that represents a resolver and since resolver is a function, the type defines that function. What you want to have is a type that represents the shape of a returned value, which is a different story, in where you loose signatures of arguments, a root value and a context. I don't know why it could be useful.

itscarlosrufo commented 5 years ago

👍, I though that it was possible to return the shape of a returned value without losing the signatures of arguments, a root value and a context.

The interesting point here is returning the shape of a returned value (in this case, Capsule), TypeScript could check if whatever you're returning matches the shape, which I've just checked it and it's doing it but it doesn't appear in VSCode as here

You can close this issue or tag it as a proposal feature, doesn't make sense put more time on it. Thanks anyways 😄

kamilkisiela commented 5 years ago

@swcarlosrj this is how TypeScript works.

When you do this:

type Foo = string;

const query = {
  foo(): Foo /* <-- */ {
    return 'Foo';
  }
}

TypeScript treats that as a shape of a returned value, not as function's signature.

To have typed arguments and others, you would have to define that signature, otherwise it's any. That's why I don't understand why not to put the TypeResolvers.Resolvers signature next to the object.

itscarlosrufo commented 5 years ago

That's what I've supposed it. Ah, I'll try that out, having no idea about TS (goal for 2019 😬)

kamilkisiela commented 5 years ago

@swcarlosrj can we close the issue now or there's something still missing?

itscarlosrufo commented 5 years ago

Sure, you can close it!