Parent type for resolver coming from a query resolver
See original GitHub issueTo handle typings of a query resolver that doesn’t directly return the right JSON, but passes data to other resolvers down the line (as parent data) I needed some weird stuff.
The use case is like this one: https://github.com/howtographql/howtographql/issues/619#issuecomment-385309639
Problem 1: One cannot use the query resolver type as-is, since it expects a particular return type
Problem 2: One cannot use the parent/root type from the other resolver type as it is whatever the one in Problem 1
returned
I ended up using only the argument types of the query resolver and returning something arbitrary. Then I extracted the type of that return value and used that as the type of the parent
argument of the other resolver. So now the return value of the query resolver is the (parent) argument type of another resolver.
// resolvers/Query.ts
export default {
feed: async (...allArgs: ArgumentTypes<QueryResolvers.FeedResolver>) => {
const [, { filter, skip, first, orderBy }, context] = allArgs
...
return {a:1, b:2}
}
}
// resolvers/Feed.ts
import { FeedResolvers, MyContext } from '../generated/resolvers-types'
import queryResolver from './Query'
export default {
links: async (parent, _args, context, info) => {
// typeof parent is now the right one: Promise<{a: number, b: number}>
const p = await parent
return (await parent).links
},
found: async (parent, _args) => {
return (await parent).links.length
},
} as FeedResolvers.Resolvers<MyContext, ReturnType<typeof queryResolver.feed>>
and i defined this two helper types
export type ArgumentTypes<F> = F extends (...args: infer A) => infer R ? A : never
// The default ReturnType generic breaks because of parent being of type never in the query resolver
export type ReturnType<F> = F extends (...args: infer A) => infer R ? R : never
Convoluted but it is super useful to know exactly what the parameter is, instantly found a bug. Would it be possible to have helpers for that in the generated code somehow?
btw, I’m new to Typescript so be easy on me please
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:5 (2 by maintainers)
Top GitHub Comments
@dbuezas By typings cannot be used directly, you mean that you need to overwrite the generics?
You don’t have to force or use
as
with the resolvers typings, just use the as-is for the entire resolver object. By default, the generated output of the resolvers plugin is an object matching the structure of your type. You can override it with TypeScript generics, and you are doing it only once, and not for each resolver field, because they should all be the same.For example:
If you have a a type:
Then, you resolvers with the generated typings should look like that:
Now, let’s say that your actual objects looks a bit different, and you are changing your
myType
resolver to return it:So declare a TypeScript interface that matches your object:
Next, use it in your Query resolver generics to tell the resolver how your
Return
object looks like:And also, use it in the type resolvers to tell it how it looks:
If you wish to avoid specifying the generics each time, you can use the
mappers
configuration, and this way you can just tell the plugin to always match betweenMyType
andMyTypeCustomStructure
:Thanks for the very comprehensive answer!
My point is that the Query resolver won’t return what is expected (in your example returns a
string
instead), so the typings for that can’t be used directly. Furthermore I wanted to have the return value of that query be automatically in synch with theparent
argument of theUser
resolver.That is why I extracted the
ArgumentsType
fromQueryResolvers.FeedResolver
but let the return type to be inferred, and then extracted that inferred return type and used it as the parent type of theFeed
resolver.(
ReturnType
is not the “native” one because that one assumes there are no args of typenever
)Since that was useful for me, I thought you may have a comment on that approach and if it makes sense to support it directly from the generated code somehow.