如何在GraphQL中动态定义新类型?基于API返回的humanoid.id命名
在GraphQL中动态创建类型的实现方案
GraphQL的SDL(Schema Definition Language)是静态的,没法直接实现"根据API返回的humanoid.id动态命名类型"的需求,你需要利用程序式Schema构建API(通过GraphQL核心类手动创建类型)来实现这个功能,具体方案如下:
1. 核心思路
先构建基础的Schema框架,在查询的resolve函数中先获取humanoid.id,再用这个id动态创建对应的类型和字段,最后返回匹配的数据结构。
2. 代码实现
const { GraphQLObjectType, GraphQLString, GraphQLSchema } = require('graphql'); // 模拟从API获取humanoid数据的函数 const fetchHumanoidFromAPI = async () => { return { id: "Humanoid-id-sh@q" }; }; // 先定义固定的Humanoid类型 const HumanoidType = new GraphQLObjectType({ name: 'Humanoid', fields: { id: { type: GraphQLString } } }); // 预留Human类型的变量,后续动态赋值 let HumanType; // 定义Query根类型,延迟解析HumanType避免初始化错误 const QueryType = new GraphQLObjectType({ name: 'Query', fields: { human: { type: () => HumanType, resolve: async () => { // 1. 从API获取humanoid数据,拿到id const humanoid = await fetchHumanoidFromAPI(); const humanoidId = humanoid.id; // 2. 用获取到的id动态创建详情类型 const DynamicDetailType = new GraphQLObjectType({ name: `${humanoidId}`, // 直接用id作为类型名 fields: { name: { type: GraphQLString }, height: { type: GraphQLString } } }); // 3. 动态构建Human类型,包含humanoid和动态字段 HumanType = new GraphQLObjectType({ name: 'Human', fields: { humanoid: { type: HumanoidType }, // 用计算属性设置动态字段名,对应动态类型 [humanoidId]: { type: DynamicDetailType, resolve: () => ({ name: "your name", height: "your height" }) } } }); // 4. 返回查询数据,包含humanoid和动态字段的数据源 return { humanoid, [humanoidId]: {} }; } } } }); // 最终创建Schema const schema = new GraphQLSchema({ query: QueryType });
3. 关键注意点
- 类型名称唯一性:确保
humanoid.id不会重复,否则会抛出"类型已存在"的错误,建议给id加固定前缀(比如HumanoidDetail_${humanoidId})避免冲突。 - 延迟解析:定义
human字段类型时用() => HumanType延迟解析,因为HumanType是动态生成的,避免初始化阶段的引用错误。 - 动态字段匹配:查询时需要用实际获取到的
humanoid.id作为字段名,才能拿到对应的详情数据。
4. 示例查询与结果
查询语句
query { human { humanoid { id } # 替换为实际返回的humanoid.id Humanoid-id-sh@q { name height } } }
返回结果
{ "data": { "human": { "humanoid": { "id": "Humanoid-id-sh@q" }, "Humanoid-id-sh@q": { "name": "your name", "height": "your height" } } } }
内容的提问来源于stack exchange,提问作者Ayman Subbagh
相关产品推荐
相关产品推荐

