Not able to match all the interfaces of a union #1179
-
Hey all, I'm facing an issue which I'm not able to presume if it's a bug or an implementation error, so it's better to ask here first than create an issue right away 😅 SummaryThe goal is to declare the return type of a mutation using a union in order to express multiple states: Success and user errors mutation($data: CreateUserInput!) {
createUser(data: $data){
... on CreateUserSuccess {
user {
id
}
}
... on EmailTakenError {
emailWasTaken
}
... on UserError {
code
message
}
}
} Implementation using TypeGraphQL:@ObjectType()
class CreateUserSuccess {
@Field(() => User)
user: User
}
@ObjectType()
class EmailTakenError {
@Field()
emailWasTaken: boolean
}
const mapMutationValueKeyToObjectType = {
user: CreateUserSuccess,
code: UserError,
emailWasTaken: EmailTakenError
}
const CreateUserPayload = createUnionType({
name: 'CreateUserPayload',
types: () => [CreateUserSuccess, EmailTakenError, UserError] as const,
resolveType: mutationValue => {
const mapperKeys = Object.keys(mapMutationValueKeyToObjectType)
const mutationValueKey = mapperKeys.find((key) => key in mutationValue)
return mapMutationValueKeyToObjectType[mutationValueKey]
}
})
@InputType()
class CreateUserInput implements Partial<User> {
@Field()
name: string
@Field()
email: string
}
@Resolver(User)
export class UserResolver {
@Mutation(() => CreateUserPayload)
createUser (@Arg('data', {
description: 'Represents the input data needed to create a new user'
}) createUserInput: CreateUserInput) {
const { name, email } = createUserInput
return createUser({ name, email })
}
} Data layerexport const createUser = async ({
name, email
}: { name: string; email: string; }) => {
const existingUser = await dbClient.user.findUnique({
where: {
email
}
})
if (existingUser) {
return {
code: ErrorCode.DUPLICATE_ENTRY,
message: "There's an existing user with the provided email.",
emailWasTaken: true
}
}
return dbClient.user.create({
data: {
name,
email
}
})
} IssueThe response doesn't resolve all of the selected fields according to their unions, even by returning fields that are related to different types if (existingUser) {
return {
code: ErrorCode.DUPLICATE_ENTRY,
message: "There's an existing user with the provided email.",
emailWasTaken: true
}
} My doubt is this case is, why |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
I'm wondering now if the expected behavior is indeed just returning one union from mutation response, in that case, would make sense to not have any data regarding const mapMutationValueKeyToObjectType = {
user: CreateUserSuccess,
code: UserError,
emailWasTaken: EmailTakenError
} |
Beta Was this translation helpful? Give feedback.
-
When it encounters Your resolve type solutions looks overengineered. It would be better to just use classes constructors directly, like |
Beta Was this translation helpful? Give feedback.
When it encounters
code: ErrorCode.DUPLICATE_ENTRY,
property, it returnsUserError
because of that.Your resolve type solutions looks overengineered. It would be better to just use classes constructors directly, like
return new EmailTakenError(...)
.