GraphQL嵌套对象类型定义、联合类型使用及查询报错问题咨询
Let's break down each of your questions with clear explanations and fixes tailored to your code:
1. 如何描述嵌套对象的类型?
描述嵌套对象类型 is straightforward—define the child object type first, then reference it in the parent object's field. You already did this correctly in your code: you created the RocketMass type first, then used it as the type for the mass field in the Rocket type.
For a more concrete example, if you wanted to add another nested object like engine to Rocket, you’d write:
type Rocket { id: ID! name: String! mass: RocketMass engine: RocketEngine # Reference the nested type } # Define the child object type first type RocketEngine { thrust: Int! fuelType: String! }
The order of type definitions doesn’t strictly matter (GraphQL parses all types first before linking them), but defining child types upfront makes your schema easier to read.
2. 如何描述联合类型?
GraphQL union types let a field return one of multiple object types. The syntax is union UnionTypeName = TypeA | TypeB, which you used perfectly for your Mass union:
union Mass = MassInt | MassFloat
Two critical rules to remember:
- Union members must be object types—you can’t use scalars (like Int/Float) or enums directly (which ties into your fourth question).
- When querying a union field, you need to use fragments to handle each possible type, since GraphQL can’t predict which type will be returned. We’ll cover this in the next question.
3. 如何使用typeDefs中定义的kg和lb属性?
Since kg and lb are of the Mass union type (they can return either MassInt or MassFloat), you can’t directly query mass { kg, lb }—GraphQL doesn’t know which version of kg (integer or float) to fetch. Instead, you need to use inline fragments to specify fields for each union member.
Here’s how to fix your GET_ROCKET query:
const GET_ROCKET = gql` query GetRocket($id: ID!){ rocket(id: $id){ name mass { kg { # Use inline fragments to handle both Mass types ... on MassInt { kg } ... on MassFloat { kg } } lb { ... on MassInt { kg } ... on MassFloat { kg } } } } } ` If you need to reuse these fragments across queries, you can define them separately: ```graphql const GET_ROCKET = gql` # Reusable fragments for Mass types fragment MassIntFields on MassInt { kg } fragment MassFloatFields on MassFloat { kg } query GetRocket($id: ID!){ rocket(id: $id){ name mass { kg { ...MassIntFields ...MassFloatFields } lb { ...MassIntFields ...MassFloatFields } } } } ` This way, your query will correctly fetch the `kg` value regardless of whether it’s an integer or float. ## 4. 为什么不能直接定义类似`union Mass2 = Int|Float`这样的联合类型? GraphQL’s rule for unions is strict: **union members can only be object types**—scalars (Int, Float, etc.), enums, or other unions aren’t allowed. The reason for this is that unions rely on the `__typename` field to distinguish between types, and scalars don’t have a `__typename` attribute. To create a union of scalar values, you have to wrap each scalar in an object type (like you did with `MassInt` and `MassFloat`) so GraphQL can identify which type is being returned. 内容的提问来源于stack exchange,提问作者J1nger

