sikanhe / gqtx

Code-first Typescript GraphQL Server without codegen or metaprogramming
458 stars 13 forks source link

Add implicit field resolution without the need of `defaultField` #48

Closed FedericoBiccheddu closed 3 years ago

FedericoBiccheddu commented 3 years ago

I was thinking about an implicit resolution of field in order to have the same behavior as GraphQL.

At the moment there are two ways of resolving fields with the same result in return: Explicit:

const droidType = t.objectType<Droid>({
  // ...
  fields: () => [
    t.field('id', {
      // Please note type is under a "configuration" object
      type: t.NonNull(t.ID), 
      resolve: (src) => src.id
    }),
    // ...
  ],
});

Implicit:

const droidType = t.objectType<Droid>({
  // ...
  fields: () => [
    // Please note the type is mandatory
    t.defaultField('id', t.NonNull(t.ID), {
      resolve: (src) => src.id
    }),
    // ...
  ],
});

To simplify the API having one way to obtain the same result in different ways, I did experiment with this approach:

The code will be something like:

const droidType = t.objectType<Droid>({
  // ...
  fields: () => [
    // Explicit resolver if needed
    t.field('id', t.NonNull(t.ID), {
      resolve: (src) => src.id
    }),

    // Implicit resolver if we want to resolve source's 'name' property
    t.field('name', t.NonNull(t.String)),
    // ...
  ],
});

What do you folks think?

n1ru4l commented 3 years ago

I like the idea.

Would the following be a compiler error?

type Droid {
  id: string;
  name: number; // this is number instead of string
}
const droidType = t.objectType<Droid>({
  // ...
  fields: () => [
    t.field('id', t.NonNull(t.ID), {
      resolve: (src) => src.id
    }),
    // will this be a compiler error because Droid["name"] is number instead of string?
    t.field('name', t.NonNull(t.String)),
  ],
});
FedericoBiccheddu commented 3 years ago

It should, but at the moment there is no inference from Src so it will pass.

I will try and update #49 to fix this scenario.