GraphQL中如何自动识别计算自定义字段所需的未请求依赖字段?
Great question! GraphQL itself doesn’t have a built-in mechanism to automatically detect when one field resolver depends on another underlying field, but TypeGraphQL has tools to handle this cleanly, and there are standard development conventions you can follow to avoid messy manual info or context workarounds.
1. Use TypeGraphQL's getSelectedFields to Auto-Include Dependencies
The core problem here is that your getUser resolver only fetches the fields the client explicitly asks for, but your age resolver needs the born_at field (which the client didn’t request). TypeGraphQL’s getSelectedFields utility fixes this by:
- Starting with the client’s requested fields
- Automatically adding any fields that your field resolvers rely on (like
born_atfor calculatingage)
Here’s how to update your code:
First, import the utility:
import { getSelectedFields } from 'type-graphql';
Then revise your getUser resolver to use this instead of the manual fields parameter:
async getUser(getUserArgs: GetUserArgs, @Info() info: GraphQLResolveInfo): Promise<User> { // Get all fields needed: client-requested + resolver dependencies const selectedFields = getSelectedFields(info); const knexFields = this.getKnexFields(selectedFields); const response = await knex.select(knexFields) .from(USER) .whereRaw('id = ?', [getUserArgs.id]); return response[0]; }
Now, even if the client only requests full_name and age, getSelectedFields will include born_at in the list because your age resolver references it. This ensures your Knex query pulls the necessary data to compute the age without manual intervention.
2. Make Sure Your User Type Defines the Dependent Field
For TypeGraphQL to track the dependency, your User object type must include the born_at field (even if clients don’t usually request it directly):
import { ObjectType, Field } from 'type-graphql'; import { DateTime } from 'graphql-scalars'; // Use a date scalar for proper GraphQL type handling @ObjectType() class User { @Field() id: string; @Field() full_name: string; @Field(() => DateTime) born_at: Date; // Required for TypeGraphQL to detect the age resolver's dependency @Field(() => Number) age: number; }
3. Follow Standard Conventions to Avoid Future Issues
To prevent similar problems down the line, stick to these practices:
- Let the framework handle field selection: Avoid passing around manual
fieldsarrays. UsinggetSelectedFieldsreduces human error and automatically accounts for resolver dependencies. - Explicitly reference dependencies: When your
ageresolver usesuser.born_at, it’s clear to other developers exactly what data it needs—no hidden magic required. - Avoid overfetching:
getSelectedFieldsonly adds the exact dependencies needed, so you won’t pull unnecessary data from the database beyond what’s required for the client’s request and resolver logic.
Why This Works
During schema building, TypeGraphQL analyzes your field resolvers to track their dependencies. When you use getSelectedFields, it combines the client’s requested fields with any hidden dependencies required by resolvers, ensuring your data layer fetches everything needed to resolve the query completely.
内容的提问来源于stack exchange,提问作者Petro Ivanenko

