Union TS generic function definitions into one type with all possible input -- output types

Working with GQL for my employer and using graphql-hooks which is being invoked inside a custom hook that handles adding headers for us as needed. I'd like to create a type definition that will allow us to denote what the expected response in the data key will be based on the input string passed as an argument. I went ahead and created a def that accepts two generic parameters, one which represents the input string literal (T) and the other which represents the expected shape of the data (U):
type UseGQLGeneric<T, U> = (
request: T, // GQL query string
requestOptions?: object
) => [RequestFn<U>, UseClientRequestResult<U>]; // U being the response body
type UseGQLGeneric<T, U> = (
request: T, // GQL query string
requestOptions?: object
) => [RequestFn<U>, UseClientRequestResult<U>]; // U being the response body
The idea being that you can import the string literal query being passed, and create a definition which types out the logical relationship between input and output, like:
type LoginQuery = UseGQLGeneric<typeof LOGIN_QUERY, { success: boolean }>;
type LoginQuery = UseGQLGeneric<typeof LOGIN_QUERY, { success: boolean }>;
I'd like to then union these definitions into one def that the function being invoked can be typed as, and accept any query string and return the corresponding value., e.g.
type UseGQLFunc = LoginQuery | OtherQuery | ThirdQuery;
type UseGQLFunc = LoginQuery | OtherQuery | ThirdQuery;
However, I'm running into an issue because it seems the argument being typed as T is always coming up as never in the final definition. Presumably because TS looks at two distinct string literals, sees that there is no way to union these types, and so assigns a value of never. Is there any way to achieve what I'm looking for, and type the function such that it dynamically returns the correct type based on the argument passed? Or will we instead need to cast each individual invocation, or handle it some other way? Sorry if something similar has been asked before, or if I'm being vague or unreasonable with what I'm asking. I hope you're all having a great day.
3 Replies
benten
benten2y ago
type UseGQLGeneric<T extends string, U> maybe?
Roren
Roren2y ago
Oh, I may be absolutely ridiculous and needed an intersection rather than a union:
type UseGQLFunc = LoginQuery & OtherQuery & ThirdQuery;
type UseGQLFunc = LoginQuery & OtherQuery & ThirdQuery;
Seems to be working as expected. I'll need to brush up on the difference between unions and intersections in this context. I'll go behind to make sure, but if this is the case I'm sorry for asking this question prematurely.
benten
benten2y ago
No need to apologise, I find the best way to figure out a problem is to ask for help. Not because I get it, but because for some reason it's like a +10 to brain function or something lmao
Want results from more Discord servers?
Add your server