persistgraphql
persistgraphql copied to clipboard
Lost type information with addPersistedQueries
Extending on #3 when using other NetworkInterface
s this type information is lost after calling this function.
As the function expects a parameter of type NetworkInterface
and returns this parameter after Object.assign
the inferred type is NetworkInterface & { query: Promise<ExecutionResult> }
.
Thus all type information of the networkInterface extending NetworkInterface
is lost.
Example
const networkInterface = addPersistedQueries(
createNetworkInterface({
uri: '/graphql',
}), // creates HTTPNetworkInterface
persistedQueries,
);
networkInterface.use(/* some middleware */);
Expectation
Above code should work, since .use()
is defined on HTTPNetworkInterface
.
Actual result
Throws with Property 'use' does not exist on type 'NetworkInterface & { query: (request: Request) => Promise<ExecutionResult>; }'.
Solution
The solution could look somewhat like this:
export function addPersistedQueries<T extends NetworkInterface>
(networkInterface: T, queryMap: OutputMap) {
let __interfaceType: T; // I think this is necessary for Generic to work correctly
// [...]
}
Yes, totally agree with this. I think the generics solution should work perfectly. Would you like to submit a PR that implements this?
Can do, but probably only by next week
Sure, that sounds great. Please let me know if I can help in some way.
Okay, is the intended use of addPersistedQueries
to call it and use the returned value or does it only enhance the existing network interface?
Replace:
let networkInterface = new GenericNetworkInterface();
networkInterface = addPersistedQueries(new GenericNetworkInterface(), queryMap);
Enhance:
let networkInterface = new GenericNetworkInterface();
addPersistedQueries(networkInterface, queryMap);
As I see it now with return Object.assign(networkInterface, { /* */ }
the existing object is enhanced, so it might be the better option to just not return the modified object but keep it as () => void
to clarify its correct usage. With that also no type information of the original network interface is lost (what is lost however is the query(request: Request) => Promise<ExecutionResult>
which matches the definition in NetworkInterface
so it should not be problematic).