error
defaults to type unknown
because your queryFn
can throw anything, that's a javascript behaviour. throw 5
will give you number
as your error type. There is no good way to assert that, so unknown is the best possible type. It's also what TypeScript does now per default since v4.4 (useUnknownInCatchVariables)
The best way to make sure that your app runs as you want is to narrow the type at runtime. if (error instanceof Error)
does the trick, and the you can safely access error.message
.
If you are using axios
, the type is actually an AxiosError
, and axios has an axios.isAxiosError(error)
helper that checks for that and also narrows the type correctly.
The alternative is to provide generics to useQuery:
useQuery<Todo[], AxiosError>(['todos'], fetchTodos)
but this is bad for a couple of reasons:
- there are actually four generics, and you remove a bunch of features by only providing two of them
- There is no guarantee that your error will really be an axios error. For example, if you use
select
, and a runtime error happens in there (because of some faulty logic), your error will be a "normal" Error
, but not an axios Error.
Alas, as you can throw anything in JS, unknown is the most correct type.
I'm also going into more details in my blog:
https://tkdodo.eu/blog/react-query-and-type-script
error.response
, it looks like you are using something like axios maybe? In that case, theerror
would be whatever axiosthrow
s on error. – Arnesoncatch
here is the error you are getting, find it's type. – Arneson