Utilizing the fully typesafe auto-generated code provided by the amazing graphql-codgen/vue
, I have streamlined its usage in my project by creating a small wrapper to simplify common configuration tasks for my Users. This includes activities such as defining cache behavior, automatically updating the cache, and deconstructing results into the appropriate types and formats.
The wrapper functions seamlessly with JS and accepts any
type inputs, however, I am keen on enhancing it with type safety. Given that graphql-codegen
already generates all methods and types in a typesafe manner, I believe there must be a way to achieve this, possibly using discriminating unions...
To illustrate my question with a code snippet: I possess this auto-generated 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>;
Now, I aim to utilize it dynamically like this while minimizing repetition:
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
// Additionally, we seek to return everything including a parsedResult
const listName = `${typename}sList`
return {
[listName]: parseResult(result),
...result
}
}
INTENT
I am determined not to duplicate the effort put into graphql-codgen by constructing a discriminated union TypeTable
. My reasoning is based on the assumption that graphql-codegen has already handled this task effectively.
My ultimate objective is to enable individuals to create a new ExamplesList.graphql
, whereby graphql-codegen processes it, making it readily accessible via useQueryList("example")
.
While the parameter is dynamically passed, it should also be feasible to obtain the correct static types by mapping the return types of all Service functions and determining the one that yields an Array<__typename>
. Or might I be mistaken? Furthermore, I suspect I need to convert the typename
parameter from a string to a string literal by extracting all potential __typenames
from Service
.
const result = Service[fnName](); //! this is the problem
This action represents just a fraction of our operations; we encapsulate and modify it further, but once the correct type is identified here, everything should fall into place smoothly.