graphql-schema
graphql-schema copied to clipboard
[Question] How can we use the types in runtime?
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?
I have the problem!
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?
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 andRepository
value type so we can not use it inappropriately. It is defined byResultType
. (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.
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
@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 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.