RFC: GCG Typegen for Graphcache's config
See original GitHub issueSummary
Right now, the cache exchange’s types seem to do a good job at preventing any type errors without manual casting. That being said, it doesn’t have the same support for type-hinting that other parts of the package (e.g., useQuery
) do. This also seems to have confused some people (e.g., #851). I think the cacheExchange could provide better type support by being transformed into a generic function that lets users provide the types that should appear in their cache, so that, e.g., when writing an optimistic response, the types of arguments available will be listed.
Proposed Solution
I can think of two ways to achieve this. First, provide manual overrides of the CacheExchangeOpts
types. This would enable graphql code generating tools to build these types. However, this makes it highly unlikely that someone would build all these types by hand, since that’d be just as slow as using the existing types. And, until the code generators tools exist, this feature would be mostly useless.
The second way would be to let something representing the schema be passed to it, and determine the types that way. I think the best candidate would be something like graphql-codegen’s typescript resolvers. Then, the cache exchange could derive the types it needs from that. I built out types that at least show it’s possible to do this for all of the fields on the cache exchange options – I’m happy to post all of those if that’s helpful, but to give an example of just one:
type ResolverMap = Record<string, Record<string, (...args) => any>>; // Simplified representation of graphql codegen's resolver type
type MapParent<T extends Record<string, AnyFunction>> = {
[P in keyof T]: ReturnType<T[P]>
}
type NewResolverConfig<T extends ResolverMap> = {
[P in keyof T]: {
[R in keyof T[P]]: (parent: MapParent<T[P]>, args: Parameters<T[P][R]>[1], cache: Cache, info: ResolverInfo) => DataField | undefined; // The return type could likely be improved – maybe Partial<ReturnType<T[P][R]>> | undefined
}
}
export interface CacheExchangeOpts<T extends ResolverMap | undefined = undefined> {
resolvers?: T extends undefined ? ResolverConfig : NewResolverConfig<T>;
// ... updates, optimistic, etc.
}
Then, a user would be able to define a type representing their schema and pass it to cache exchange to get type suggestions:
type SchemaResolver = {
UserDefinedType: {
field: (parent: UserDefinedType, args: { id: string }) => DataField
}
}
const myCacheExchange = cacheExchange<SchemaResolver>({ ... });
// Or, of course
const cacheOptions: CacheExchangeOpts<SchemaResolver> = {
...
}
const myCacheExchange = cacheExchange(cacheOptions);
(Side note – this is my first time contributing to this repo, using a broad definition of the word “contribute”, so if there’s something about this issue I should change to make it more useful, let me know and I’m happy to do so)
Issue Analytics
- State:
- Created 3 years ago
- Reactions:11
- Comments:15 (7 by maintainers)
Covered in:
Once merged we’ll be able to do:
make a
codegen.yaml
and runyarn graphql-codegen --config codegen.yml
Finally you’ll be able to import the generic from
__generated__/graphql.ts
and use itEnjoy a typed schema!
Edit: published 16th of May
@prichodko that would be great yea, I’ve honestly not really gotten to it but from using it myself I think it’s a great addition for the docs and people to just start out with.