graphql-schema icon indicating copy to clipboard operation
graphql-schema copied to clipboard

[Question] How can we use the types in runtime?

Open frank-zsy opened this issue 3 years ago • 6 comments

Right now all the types are defined as type so we can use them in program to get the types. But actually I think we can also use the types to generate the GraphQL SQL query string automatically.

So I think if we can define the types as class and use a class instance as the parameter so the underlying program can generate query string from the instance and return the right type as well. Are there any side effects if we use class instead of type to do this?

frank-zsy avatar May 14 '21 05:05 frank-zsy

I have the problem!

wengzhenjie avatar May 14 '21 05:05 wengzhenjie

I don't quite understand what you are suggestion. Do you want to start a PR to show what you mean, and we can discuss there?

gr2m avatar May 14 '21 07:05 gr2m

Thanks for the reply.

I still did not figure it out but I can give a simple example to show what I mean:

class Repository {
  id: number;
  name: string;
  issue: {
    number: number;
    body: string;
    comment: {
      id: number;
      body: string;
    }
  };
}

type SchemaType<T> = { [ P in keyof T ]?: T[P] extends object ? SchemaType<T[P]> : true };
type ResultType<T, G = SchemaType<T>> = { [ P in (keyof T & keyof G) ]: G[P] extends object ? ResultType<T[P], G[P]> : T[P] };

function getPartialData<T>(_type: new () => T, schema: SchemaType<T>): ResultType<T, typeof schema> {
  const genData = (obj: any) => {
    const res: any = {};
    for (const k in obj) {
      if (typeof obj[k] === 'object') {
        res[k] = genData(obj[k]);
      } else {
        res[k] = 1;
      }
    }
    return res;
  };
  return genData(schema);   // generate data, can generate GraphQL query by schema and return result.
}

const schema: SchemaType<Repository> = {
  id: true,
  issue: {
    number: true,
    comment: {
      id: true,
    }
  },
};

console.log(getPartialData(Repository, schema));  // { id: 1, issue: { number: 1, comment: { id: 1 } } }

In above code, we can query the repository data from the getPartialData function with Repository class and a schema config. And the constraints are:

  • The schema config structure we can pass into the function is constrained by the first parameter which is the data type we request. It is defined by SchemaType so we can not pass in an invalid structure and the values should only be true.
  • The returned type should be inferred from the Repository class and the schema type which means we will get the result as a type which contains schema keys and Repository value type so we can not use it inappropriately. It is defined by ResultType. (Which I can not implement because I am not quite familiar with TypeScript type system).

But I think it makes really easy for up-layer program to use because we do not need to write GraphQL query ourselves and the underlying code can also handle paginate data properly which also will make it easier to use.

frank-zsy avatar May 16 '21 11:05 frank-zsy

I'm sorry I still don't follow 100%, but it sounds interesting. If you figure it out, please let me know! I'd love to improve the developer experience for sending GraphQL queries, ideally without adding a lot of code to octokit

gr2m avatar Jun 11 '21 17:06 gr2m

@frank-zsy are you looking to generate factories? This is exactly what zhouzi/graphql-codegen-factories does. For example, given the following schema:

type Repository {
  id: ID!
  name: String!
}

It generates something similar to:

export function createRepositoryMock(props: Partial<Repository>): Repository {
  return {
    __typename: "Repository",
    id: "",
    name: "",
    ...props,
  };
}

The default values can be customized. If that's what you are looking for, I would be happy to add it to my fork: zhouzi/graphql-schema

zhouzi avatar May 19 '22 18:05 zhouzi

@zhouzi Great, I mean something like that. So like in the example we can use the type as a parameter and pass in as props and it will return the same type. I don't look into the code but how did you handle the array type like embedded edges and nodes which is quite annoying and the pagination is also a tricky work.

frank-zsy avatar May 22 '22 09:05 frank-zsy