In RTK, I'm using a custom baseQuery
to wrap axios, following the general guidance here. However, I can't seem to figure out a way to use conditional typing for the BaseQueryArg
type. For example, I'd like to be able to have my baseQuery function take in the following argument object:
{
url: string
method: "GET" | "PUT" | "POST" | "DELETE"
body: any
}
But, rather than have body
be any
, or even a stricter union, I'd like to have it vary depend on the type of method
. So, for example, if this was a simple function I would type it like so:
function myBaseQueryFunction<T extends "GET"|"POST">(args: {
url: string
method: T
body: T extends "POST" ? {someBodyData: string} : null
}){
// do the query
}
However, I can't seem to find any way to use that kind of typing for the function I pass to baseQuery
and have it properly restrict the return types of of my query
endpoints. Even if I don't use the BaseQueryFn
utility type and, instead, manually type a function like the one above and then pass it to baseQuery
, I still don't get the restriction on query
's return that I want.
Is there anyway to do this kind of conditional typing of baseQuery
?
Per the accepted answer below, the simplest way to handle this is with a discriminated union on method, e.g.:
type BaseQueryDiscriminatedArg =
| {
url: string
method: "POST"
body: {someBodyData: string}
}
| {
url: string
method: "GET"
body?: null
}
and then your BaseQueryFn
type is just BaseQueryFn<BaseQueryDiscriminatedArg>
I assume this should be possible by using a discriminated union type for the argument, using method
as the discriminator. Overloads or generics won't work, since TS cannot map correctly over those, hence the wrong resulting types.
If you have more problems with that, a chat might help more. Just stop by in the Redux channel on Reactiflux