Skip to content

Commit 19d755c

Browse files
committed
2 parents 0658f3f + 2eec65e commit 19d755c

File tree

3 files changed

+66
-8
lines changed

3 files changed

+66
-8
lines changed

docs/graphql.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ You can use [GraphQL-Codegen](https://graphql-code-generator.com/) to generate r
1313

1414
## Examples
1515

16-
- [basic-graphql-request](../docs/examples/basic-graphql-request) (The "basic" example, but implemented with [`graphql-request`](https://github.com/prisma-labs/graphql-request))
16+
- [basic-graphql-request](../examples/react/basic-graphql-request) (The "basic" example, but implemented with [`graphql-request`](https://github.com/prisma-labs/graphql-request))

docs/typescript.md

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,73 @@ Things to keep in mind:
1212
- It is **highly recommended that you lock your react-query package version to a specific patch release and upgrade with the expectation that types may be fixed or upgraded between any release**
1313
- The non-type-related public API of React Query still follows semver very strictly.
1414

15-
## Defining Custom Hooks
15+
## Type Inference
1616

17-
When defining a custom hook you need to specify the result and error types, for example:
17+
Types in React Query generally flow through very well so that you don't have to provide type annotations for yourself
1818

1919
```ts
20-
function useGroups() {
21-
return useQuery<Group[], Error>('groups', fetchGroups)
20+
const { data } = useQuery(['test'], () => Promise.resolve(5))
21+
// ^? const data: number | undefined
22+
```
23+
24+
[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFC8MQAdqnhIAJnRh0icALwoM2XHgAUAbSqDkIAEa4qAXQA0cFQEo5APjgAFciGAYAdLVQQANgDd0KgKxmzXgB6ILgw8IA9AH5eIA)
25+
26+
```ts
27+
const { data } = useQuery(['test'], () => Promise.resolve(5), { select: data => data.toString()})
28+
// ^? const data: string | undefined
29+
```
30+
31+
[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFC8MQAdqnhIAJnRh0icALwoM2XHgAUAbSox0IqgF0ANHBUBKOQD44ABXIhgGAHS1UEADYA3dCoCsxw0gwu6EwAXHASUuZhknT2MBAAyjBQwIIA5iaExrwA9Nlw+QUAegD8vEA)
32+
33+
This works best if your `queryFn` has a well-defined returned type. Keep in mind that most data fetching libraries return `any` per default, so make sure to extract it to a properly typed function:
34+
35+
```ts
36+
const fetchGroups = (): Promise<Group[]> => axios.get('/groups').then(response => response.data)
37+
38+
const { data } = useQuery(['groups'], fetchGroups)
39+
// ^? const data: Group[] | undefined
40+
```
41+
42+
[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFCiSw4dAB7AIqUuUpURY1Nx68YeMOjgBxcsjBwAvIjjAAJgC44AO2QgARriK9eDCOdTwS6GAwAWmiNon6ABQAlGYAClLAGAA8vtoA2gC6AHx6qbLiAHQA5h6BVAD02Vpg8sGZMF7o5oG0qJAuarqpdQ0YmUZ0MHTBDjxOLvBInd1EeigY2Lh4gfFUxX6lVIkANKQe3nGlvTwFBXAHhwB6APxwA65wI3RmW0lwAD4o5kboJMDm6Ea8QA)
43+
44+
## Type Narrowing
45+
46+
React Query uses a [discriminated union type](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions) for the query result, discriminated by the `status` field and the derived status boolean flags. This will allow you to check for e.g. `success` status to make `data` defined:
47+
48+
```ts
49+
const { data, isSuccess } = useQuery(['test'], () => Promise.resolve(5))
50+
51+
if (isSuccess) {
52+
data
53+
// ^? const data: number
54+
}
55+
```
56+
57+
[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFC8MQAdqnhIAJnRh0ANHGCoAysgYN0qVETgBeFBmy48ACgDaVGGphUAurMMBKbQD44ABXIh56AHS1UEADYAbuiGAKx2dry8wCRwhvJKKmqoDgi8cBlwElK8APS5GQB6APy8hLxAA)
58+
59+
## Typing the error field
60+
61+
The type for error defaults to `unknown`. This is in line with what TypeScript gives you per default in a catch clauses (see [useUnknownInCatchVariables](https://devblogs.microsoft.com/typescript/announcing-typescript-4-4/#use-unknown-catch-variables)). The safest way to work with `error` would be to perform a runtime check; another way would be to explicitly define types for `data` and `error`:
62+
63+
```ts
64+
const { error } = useQuery(['groups'], fetchGroups)
65+
// ^? const error: unknown
66+
67+
if (error instanceof Error) {
68+
error
69+
// ^? const error: Error
2270
}
2371
```
2472

73+
[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFCiSw4dAB7AIqUuUpURY1Nx68YeMOjgBxcsjBwAvIjjAAJgC44AO2QgARriK9eDCOdTwS6GAwAWmiNon6ABQAlGYAClLAGAA8vtoA2gC6AHx6qbLiAHQA5h6BVAD02Vpg8sGZMF7o5oG0qJAuarqpdQ0YmUZ0MHTBDjxOLvBIuORQRHooGNi4eIHxVMV+pVSJADSkHt5xpb08BQVwh0cAegD8fcAkcIEj0IaDdOYM6BBXAKJQo8GIvIe3ULx9nAzrxCEA)
74+
75+
```ts
76+
const { error } = useQuery<Group[], Error>(['groups'], fetchGroups)
77+
// ^? const error: Error | null
78+
```
79+
80+
[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFCiSw4dAB7AIqUuUpURY1Nx68YeMOjgBxcsjBwAvIjjAAJgC44AO2QgARriK9eDCOdTwS6GAwAWmiNon6ABQAlGYAClLAGAA8vtoA2gC6AHx6qbLiAHQA5h6BVAD02Vpg8sGZMF7o5oG0qJAuarqpdQ0YmUZ0MHTBDjxOLvBIuORQRHooGNi4eLElSQA0cACiUKPJgfFUxX6lVIlL7p4+Jai9PAUFcNc3AHoA-LxAA)
81+
2582
## Further Reading
2683

2784
For tips and tricks around type inference, have a look at [React Query and TypeScript](../community/tkdodos-blog#6-react-query-and-typescript) from

src/reactjs/tests/useQueries.test.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,13 +1058,14 @@ describe('useQueries', () => {
10581058

10591059
await sleep(30)
10601060

1061-
expect(results.length).toBe(3)
10621061
expect(results[0]).toMatchObject([
10631062
{ data: undefined },
10641063
{ data: undefined },
10651064
])
1066-
expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])
1067-
expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])
1065+
expect(results[results.length - 1]).toMatchObject([
1066+
{ data: 1 },
1067+
{ data: 2 },
1068+
])
10681069
})
10691070

10701071
it('should throw if the context is necessary and is not passed to useQueries', async () => {

0 commit comments

Comments
 (0)