TypeGraphQL中createClient突变触发ArgumentValidationError问题排查
问题:TypeGraphQL创建客户突变时出现ArgumentValidationError错误
我用TypeGraphQL搭建了一个可查询项目及关联客户的简易API,调用createClient突变时收到ArgumentValidationError,提示an unknown value was passed to the validate function。直接传参数给突变没问题,但用解构输入对象的方式就触发错误,相关代码如下:
Client Schema
import { ObjectType, Field, ID } from "type-graphql"; @ObjectType() class ClientSchema { @Field(type => ID) id: string @Field() name: string @Field() email: string @Field() phone: string } export default ClientSchema
Client Resolver
import { Arg, Field, InputType, Mutation, Query, Resolver } from "type-graphql"; import exampleClients from "../utils/clients"; import ClientSchema from "../schemas/ClientsSchema"; @InputType() class CreateClassInput { @Field() name: string @Field() email: string @Field() phone: string } @Resolver() class ClientResolver { @Query((returns) => [ClientSchema]) async clients() { return exampleClients; } @Query((returns) => ClientSchema) async client(@Arg("id") id: string) { const client = exampleClients.find((client) => client.id === id); if (!client) throw new Error("No such client"); return client; } @Mutation((returns) => ClientSchema) async createClient(@Arg("data") createClassData: CreateClassInput) { const { name, email, phone } = createClassData; const newClient: ClientSchema = { id: String(exampleClients.length + 1), name, email, phone }; exampleClients.push(newClient); return newClient; } } export default ClientResolver;
GraphQL Query
mutation createClient { createClient(data: { name: "Test Name", email: "Test Email", phone: "Test phone" }) { name } }
问题原因与修复方案
核心错误
你把TypeGraphQL的@ObjectType()装饰的ClientSchema直接当成了普通TypeScript类型来断言newClient的类型。但@ObjectType()装饰器会给类添加额外的元数据属性,这些属性不属于业务数据,当验证器处理这个对象时,就会识别到未知值,抛出ArgumentValidationError。
修复步骤
- 定义独立的TS接口描述Client结构
在ClientSchema文件里添加一个普通的TypeScript接口,用来描述客户数据的结构,和GraphQL的输出类型解耦:
import { ObjectType, Field, ID } from "type-graphql"; // 新增:普通TS接口,描述客户数据结构 export interface Client { id: string; name: string; email: string; phone: string; } @ObjectType() class ClientSchema implements Client { // 让ObjectType实现这个接口 @Field(type => ID) id: string @Field() name: string @Field() email: string @Field() phone: string } export default ClientSchema
- 修改newClient的类型断言
在Resolver里,用新定义的Client接口来断言newClient的类型,而不是用ClientSchema:
// 先导入新增的Client接口 import ClientSchema, { Client } from "../schemas/ClientsSchema"; // ... 其他代码不变 @Mutation((returns) => ClientSchema) async createClient(@Arg("data") createClassData: CreateClassInput) { const { name, email, phone } = createClassData; // 这里改用Client接口断言类型 const newClient: Client = { id: String(exampleClients.length + 1), name, email, phone }; exampleClients.push(newClient); return newClient; }
- 可选优化:修正输入类型名称
你的输入类型叫CreateClassInput,和业务(创建客户)不符,建议改成CreateClientInput,避免后续混淆:
@InputType() class CreateClientInput { // 修改名称 @Field() name: string @Field() email: string @Field() phone: string } // 同时修改突变的参数类型 async createClient(@Arg("data") createClientData: CreateClientInput) { // ... 代码不变 }
为什么直接传参数没问题?
直接传参数时,没有涉及到用ClientSchema作为类型断言的操作,不会引入装饰器添加的额外元数据,所以验证器不会检测到未知值。
内容的提问来源于stack exchange,提问作者SumitN
相关产品推荐
相关产品推荐

