-
I am attempting to create an input struct for the purposes of pagination that takes a generic type for one of the properties. I want that generic to accept another GraphQLInputObject but I am getting this error:
Here is my code:
and a sample of one of the structs that will be used for type T (ie
How do I correctly do this? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
@bnhardy yup, at the moment What you're trying to reach here is a bit fundamentally incorrect, because GraphQL types system has no notion of generics at all. Try to express the same thing using SDL (GraphQL schema definition language), and you won't be able to. So... what happens, actually? When you write: #[derive(GraphQLInputObject, Serialize, Debug)]
pub struct ConnectionParams<T> {
pub after: Option<String>,
pub first: Option<i32>,
pub params: Option<T>,
} You define in GraphQL schema a input ConnectionParams {
after: String
first: Int
params: ??? # what type should be here?
} We should know the Then, let's place input ConnectionParams {
after: String
first: Int
params: UserParams
} It's OK, but then we want to use a input ConnectionParams {
after: String
first: Int
params: PaymentParams
} Ooops! We cannot have the same GraphQL type declared twice with the same name but different fields! To have this, we should do the monomorphization of "generic" GraphQL type by hand and specify different names for different types: input UserConnectionParams {
after: String
first: Int
params: UserParams
}
input PaymentConnectionParams {
after: String
first: Int
params: PaymentParams
} So, unfortunately, at the moment, you don't have any other options rather than duplicating declarations in Rust: #[derive(GraphQLInputObject, Serialize, Debug)]
pub struct UserConnectionParams {
pub after: Option<String>,
pub first: Option<i32>,
pub params: Option<UserParams>,
}
#[derive(GraphQLInputObject, Serialize, Debug)]
pub struct PaymentConnectionParams {
pub after: Option<String>,
pub first: Option<i32>,
pub params: Option<PaymentParams>,
} In future, perhaps, we will be able to support some kind of templating GraphQL types from Rust generic types. Though, being somewhat an obvious feature, it's far from being trivial to implement, considering it has a solid design and good ergonomics, as would require to build a rich compile-time introspection system, which may end very fast with Rust not being able to express something. And, also, templating doc comments and type names maybe quite a weird feature for a rustacean. If you're too concerned with a code repetition, you may declare a small declarative macro for defining such macro_rules! connection_params {
($name:ident, $params:type) => {
#[derive(GraphQLInputObject, Serialize, Debug)]
pub struct $name {
pub after: Option<String>,
pub first: Option<i32>,
pub params: Option<$params>,
}
}
}
connection_params!(UserConnectionParams, UserParams)
connection_params!(PaymentConnectionParams, PaymentParams) |
Beta Was this translation helpful? Give feedback.
-
Thank you for the answer. It was code duplication I was mainly trying to avoid. That macro may prove helpful. |
Beta Was this translation helpful? Give feedback.
@bnhardy yup, at the moment
GraphQLInputObject
macro cannot work with generics. Unfortunately, even when it will be able to, it won't allow your use case anyway.What you're trying to reach here is a bit fundamentally incorrect, because GraphQL types system has no notion of generics at all. Try to express the same thing using SDL (GraphQL schema definition language), and you won't be able to.
So... what happens, actually?
When you write:
You define in GraphQL schema a
ConnectionParams
input object like this: