Skip to content

feature request: add option to output interface props of interfaces as partials for types with separated field resolvers #263

Description

@BigsonLvrocha

Hello,

In graphql-yoga it is common to have a field in a type that is resolved with a separated function, so the main resolver will have to return the object with those fields missing for it to be fetched later, if queried. But the interfaces generated by gql2ts do not allow undefined in those fields.

I've been doing a workaround by defining the return of queries with Partial, but the problem is when those types are nested within another type, for instance, mutation response payload. I wished to use the generated interfaces as a helper in the resolvers return definition, but I can't assign Partial to INode type.

Example, in the snippet bellow, it is shown the resolvers for the type "Post", which has the field "Author" that can be fetched separately. I can define post query's return as Partial but I can't define the UserCreatePost mutation's return as IUserCreatePostPayload because I need to assign a full IPost object, making me having to define those types or just strip away the return type definition, which makes the library a bit pointless for this use case, it certainly makes IUserCreatePostPayload generation pointless

typePostimplementsNode {
id: ID!_id: String!title: String!description: StringauthorId: String!author: User!
}
typeMutation {
UserCreatePost(input: UserCreatePostInput!): UserCreatePostPayload
}
typeQuery {
post(id: ID!): Postfeed(first: Int, after: String, last: Int, before: String): PostConnection
}
inputUserCreatePostInput {
title: String!description: StringclientMutationId: String
}
typeUserCreatePostPayload {
error: Stringpost: PostclientMutationId: String
}
exportconstpost2IPost: model2Node<Post,GQL.IPost>=(post: Post): Partial<GQL.IPost>=>({_id: post._id,id: idToGraphqlId(post._id,idPrefix),title: post.title,description: post.description,authorId: post.authorId,});exportconstresolvers: ResolverMap={Mutation: {UserCreatePost: async(_,{input: { description, clientMutationId, title }}: GQL.IUserCreatePostOnMutationArguments,{ sequelize, userId })=>{const PostModel =sequelize.models.PostasModelCtor<Post>;constpost=(awaitPostModel.create({
description,
title,authorId: userId}))asPost;return{error: null,post: post2IPost(post),clientMutationId: clientMutationId||null};}},Query: {post: async(_,{id: graphId}: GQL.IPostOnQueryArguments,{ sequelize })=>{const PostModel =sequelize.models.PostasModelCtor<Post>;constid=graphqIdToId(graphId,"post");constpostA=(awaitPostModel.findByPk(id))asPost;if(!postA){returnnull;}returnpost2IPost(postA);},
feed
},Post: {author: async(parent,_,{ sequelize }): Promise<Partial<GQL.IUser>>=>{const UserModel =sequelize.models.UserasModelCtor<User>;constuser=(awaitUserModel.findByPk(parent.authorId))asUser;returnuser2IUser(user);},}};

So, my idea would be an option to output types like this:

interfaceIUserCreatePostPayload{error: string|null;post: IPost|null;clientMutationId: string|null;}

With an optional "shallow" type like this

interfaceIShallowUserCreatePostPayload{error: string|null;post: IPost|null|Partial<IPost>;clientMutationId: string|null;}

They could be named as shallow interfaces and be generated side by side with the others so it won't break other ppl's code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions