GraphQL.js:如何在resolveType函数中使用接口作为默认回退类型?
解决GraphQL resolveType无匹配类型时返回通用类型的问题
我明白你的困扰——当数据库突然多出了Schema里没定义的类型(比如你说的BookType),原来的resolveType函数就会因为找不到匹配类型而报错。别担心,咱们可以通过添加一个兜底的通用类型来解决这个问题,下面是完整的实现方案:
第一步:定义通用兜底类型
首先创建一个GenericType,用来处理所有未匹配到已定义类型的数据。你可以根据实际需求给它加通用字段,甚至保留一个明确的__typename来标识这是兜底类型:
const GenericType = new GraphQLObjectType({ name: "GenericType", fields: () => ({ name: { type: GraphQLString }, // 可选:明确返回类型名称,方便前端识别 __typename: { type: new GraphQLNonNull(GraphQLString), resolve: () => "GenericType" }, // 如果需要接收任意字段,可以用GraphQLJSON(需要额外安装graphql-type-json包) // extraData: { type: GraphQLJSON } }) });
第二步:修改resolveType函数,添加兜底逻辑
在接口类型的resolveType里,先判断已有的类型(比如UserType和MovieType),如果都匹配不上,就返回咱们刚定义的GenericType:
const EntityInterface = new GraphQLInterfaceType({ name: "Entity", fields: () => ({ name: { type: GraphQLString } }), resolveType: (obj) => { // 按字段特征判断UserType(比如有nick字段) if (obj.nick) { return UserType; } // 按字段特征判断MovieType(比如有director字段) if (obj.director) { return MovieType; } // 兜底:所有未匹配的类型都返回GenericType return GenericType; } });
第三步:把通用类型加入Schema
别忘了把GenericType添加到Schema的types数组里,否则GraphQL会找不到这个类型:
const schema = new GraphQLSchema({ query: RootQuery, types: [UserType, MovieType, GenericType] // 加入通用类型 });
完整可运行代码示例
这里是包含测试数据的完整代码,其中特意加入了未定义的BookType数据:
const { graphql, GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLNonNull, GraphQLList, GraphQLInterfaceType } = require("graphql"); // 1. 定义通用兜底类型 const GenericType = new GraphQLObjectType({ name: "GenericType", fields: () => ({ name: { type: GraphQLString }, __typename: { type: new GraphQLNonNull(GraphQLString), resolve: () => "GenericType" } }) }); // 2. 定义已有的UserType和MovieType const UserType = new GraphQLObjectType({ name: "UserType", fields: () => ({ name: { type: GraphQLString }, nick: { type: GraphQLString } }) }); const MovieType = new GraphQLObjectType({ name: "MovieType", fields: () => ({ name: { type: GraphQLString }, director: { type: GraphQLString } }) }); // 3. 定义接口类型,添加resolveType兜底逻辑 const EntityInterface = new GraphQLInterfaceType({ name: "Entity", fields: () => ({ name: { type: GraphQLString } }), resolveType: (obj) => { if (obj.nick) return UserType; if (obj.director) return MovieType; // 兜底返回通用类型 return GenericType; } }); // 4. 定义根查询 const RootQuery = new GraphQLObjectType({ name: "RootQueryType", fields: { entities: { type: new GraphQLList(EntityInterface), resolve: () => DATA } } }); // 测试数据:包含新增的BookType数据 const DATA = [ { name: "catherine woolf", nick: "catherine" }, // UserType { name: "Inception", director: "Christopher Nolan" }, // MovieType { name: "The Great Gatsby", author: "F. Scott Fitzgerald" } // 未定义的BookType ]; // 5. 创建Schema并加入所有类型 const schema = new GraphQLSchema({ query: RootQuery, types: [UserType, MovieType, GenericType] }); // 测试查询 graphql(schema, ` query { entities { __typename name ... on UserType { nick } ... on MovieType { director } ... on GenericType { name } } } `).then(result => console.log(JSON.stringify(result, null, 2)));
额外小技巧
如果你的数据里有明确的类型标识字段(比如obj.type = "Book"),可以用更清晰的switch判断:
resolveType: (obj) => { switch(obj.type) { case "User": return UserType; case "Movie": return MovieType; default: return GenericType; } }
这样代码可读性更高,也更易于维护~
内容的提问来源于stack exchange,提问作者Everettss
相关产品推荐
相关产品推荐

