query
query copied to clipboard
make TError default to Error instead of unknown
context
In JavaScript, you can throw anything, even literals like 5 or Promises (?? suspense). That is why the generic for the type TError defaults to unknown. This is in line with how TypeScript itself handles errors in catch clauses since v4.4.
This is not very practical. Unless you explicitly throw a non-error, error will be at least of type Error. If you use axios, it might be of type AxiosError, but that is also not guaranteed. For example, if you have a runtime error in select, that will be caught, and it puts your query into error state. The error will be of type Error then.
Practically, it means that you either fall back to runtime checks:
const { error } = useQuery(...)
if (error instanceof Error) {
// do something with error.message
}
or, you pass a generic to useQuery:
const { error, isError } = useQuery<Todos, Error>(...)
if (isError) {
// do something with error.message
}
The second approach is bad for two reasons:
TErroris the second generic, so you also have to annotate the first generic, which is the return type of the queryFn. This could actually be inferred.useQueryhas 4 generics, and if you only provide two of them, the other two will fall back to their default value instead of being inferred from their usage. That meansselectwill not work as expected:
const { error, isError } = useQuery<Todos, Error>({
queryKey: ['todos'],
queryFn: fetchTodos,
select: (data) => data[0],
})
if (isError) {
// do something with error.message
}
You'll get a weird error about no overload matching, see this TypeScript Playground.
proposal
- on type level, make the
TErrorgeneric default toErrorinstead ofunknown - no runtime changes. If you throw something else, your types might be wrong.
- we should document this, and @tannerlinsley mentioned he knows a way to overwrite the types for
Errorglobally.
- we should document this, and @tannerlinsley mentioned he knows a way to overwrite the types for
Isn't any a better fit than Error ?
That would be pretty unsafe to work with. unknown is "correct" but also inconvenient. Trying to find the middle ground here
Agree that any would be more unsafe than unknown IMO Error is better here, if it doesn't fit the Developer's need we can't still infer other types, but most of the time we use Error. I can work on this one if you want @TkDodo ?
Gotta remember that this just a default generic, too. Easily overridden and even inferred through usage in most places.
If I understand this correctly, we need to change all the TError generic types for core and for react-query, vue-query, etc to Error cc @tannerlinsley
Correct
got it! can you assign this to me?