I have fully typesafe auto-generated code by the awesome graphql-codgen/vue
.
I use it in my project by building a little wrapper so my Users don't have to do common config tasks every call. Like e.g. defining cache-behavior, auto-update cache, destructuring result in right types and format.
The wrapper workers with JS and with any
but I also want it to be typesafe and since graphql-codegen
already generates all types and methods in a typesafe way, I figure there has to be a way to do this. Somehow with discriminating unions I figure...
So boiled down to example code my question is: I have this autogenerated code:
//File GQLService.ts
export type CustodiansList = (
{ __typename: 'Query' }
& { custodiansList?: Maybe<Array<(
{ __typename: 'Custodian' }
& Pick<Custodian, 'id' | 'name' | 'street' | 'zip' | 'city' | 'telephone' | 'createdAt' | 'updatedAt'>
)>> }
);
type ReactiveFunctionCustodiansList = () => CustodiansListVariables
/**
* __useCustodiansList__
*
* To run a query within a Vue component, call `useCustodiansList` and pass it any options that fit your needs.
* When your component renders, `useCustodiansList` returns an object from Apollo Client that contains result, loading and error properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://v4.apollo.vuejs.org/guide-composable/query.html#options;
*
* @example
* const { result, loading, error } = useCustodiansList(
* {
* }
* );
*/
export function useCustodiansList(variables?: CustodiansListVariables | VueCompositionApi.Ref<CustodiansListVariables> | ReactiveFunctionCustodiansList, baseOptions?: VueApolloComposable.UseQueryOptions<CustodiansList, CustodiansListVariables>) {
return VueApolloComposable.useQuery<CustodiansList, CustodiansListVariables>(CustodiansListDocument, variables, baseOptions);
}
export type CustodiansListCompositionFunctionResult = ReturnType<typeof useCustodiansList>;
and now I want to just use it "dynamically" like this with the least amount of DRY:
import * as Service from "./GQLService"; // from above
// e.g. typename = "custodian"
function useQueryList(typename:string) {
const fnName = toFunctionName(typename) // e.g. useCustodiansList
const result = Service[fnName](); //! this is the problem
// we also want to return everything including a parsedResult
const listName = `${typename}sList`
return {
[listName]: parseResult(result),
...result
}
}
INTENT
I really don't want to have to recreate all the work done by graphql-codgen by having to create a discriminated union TypeTable
like in some other question answered, because I figure all that work is already done by graphql-codegen.
My goal would be that somebody could just create a new ExamplesList.graphql
, graphql-codegen
wraps it and then its ready to use by useQueryList("example")
So although this is a dynamically passed parameter, it also has to be possible to get the right static types by somehow map the return types of all Service functions and then get the one that return a Array<__typename>
or am I wrong? And I think I have to somehow have to boil down typename
parameter from a string to a string literal by parsing all possibles __typenames
from Service
const result = Service[fnName](); //! this is the problem
is not actually all we are doing, we wrap and transform it some more, but once I get the correct type here, everything should be fine.