Skip to content

Commit f9e3ad9

Browse files
committed
usage with typescript
1 parent d74a3ce commit f9e3ad9

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

docs/rtk-query/usage-with-typescript.mdx

+132
Original file line numberDiff line numberDiff line change
@@ -703,3 +703,135 @@ function AddPost() {
703703
)
704704
}
705705
```
706+
707+
## Schema Validation
708+
709+
Endpoints can have schemas for runtime validation of various values. Any [Standard Schema](https://standardschema.dev/) compliant library can be used. See [API reference](./api/createApi.mdx#schema-validation) for full list of available schemas.
710+
711+
When following the default approach of explicitly specifying type parameters for queries and mutations, the schemas will be required to match the types provided.
712+
713+
```ts title="Explicitly typed endpoint" no-transpile
714+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
715+
import * as v from 'valibot'
716+
717+
const postSchema = v.object({
718+
id: v.number(),
719+
name: v.string(),
720+
})
721+
type Post = v.InferOutput<typeof postSchema>
722+
723+
const api = createApi({
724+
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
725+
endpoints: (build) => ({
726+
getPost: build.query<Post, { id: number }>({
727+
query: ({ id }) => `/post/${id}`,
728+
responseSchema: postSchema, // errors if type mismatch
729+
}),
730+
}),
731+
})
732+
```
733+
734+
Schemas can also be used as a source of inference, meaning that the type parameters can be omitted.
735+
736+
```ts title="Implicitly typed endpoint" no-transpile
737+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
738+
import * as v from 'valibot'
739+
740+
const postSchema = v.object({
741+
id: v.number(),
742+
name: v.string(),
743+
})
744+
type Post = v.InferOutput<typeof postSchema>
745+
746+
const api = createApi({
747+
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
748+
endpoints: (build) => ({
749+
getPost: build.query({
750+
// infer arg from here
751+
query: ({ id }: { id: number }) => `/post/${id}`,
752+
// infer result from here
753+
responseSchema: postSchema,
754+
}),
755+
getTransformedPost: build.query({
756+
// infer arg from here
757+
query: ({ id }: { id: number }) => `/post/${id}`,
758+
// infer untransformed result from here
759+
rawResponseSchema: postSchema,
760+
// infer transformed result from here
761+
transformResponse: (response) => ({
762+
...response,
763+
published_at: new Date(response.published_at),
764+
}),
765+
}),
766+
}),
767+
})
768+
```
769+
770+
:::warning
771+
772+
Schemas should _not_ perform any transformation that would change the type of the value.
773+
774+
```ts title="Incorrect usage" no-transpile
775+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
776+
import * as v from 'valibot'
777+
import { titleCase } from 'lodash'
778+
779+
const postSchema = v.object({
780+
id: v.number(),
781+
name: v.pipe(
782+
v.string(),
783+
v.transform(titleCase), // fine - string -> string
784+
),
785+
published_at: v.pipe(
786+
v.string(),
787+
// highlight-next-line
788+
v.transform((s) => new Date(s)), // not allowed!
789+
v.date(),
790+
),
791+
})
792+
type Post = v.InferOutput<typeof postSchema>
793+
794+
const api = createApi({
795+
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
796+
endpoints: (build) => ({
797+
getPost: build.query<Post, { id: number }>({
798+
query: ({ id }) => `/post/${id}`,
799+
responseSchema: postSchema,
800+
}),
801+
}),
802+
})
803+
```
804+
805+
Instead, transformation should be done with `transformResponse` and `transformErrorResponse` (when using `query`) or inside `queryFn` (when using `queryFn`).
806+
807+
```ts title="Correct usage" no-transpile
808+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
809+
import * as v from 'valibot'
810+
811+
const postSchema = v.object({
812+
id: v.number(),
813+
name: v.string(),
814+
published_at: v.string(),
815+
})
816+
type RawPost = v.InferOutput<typeof postSchema>
817+
type Post = Omit<RawPost, 'published_at'> & { published_at: Date }
818+
819+
const api = createApi({
820+
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
821+
endpoints: (build) => ({
822+
getPost: build.query<Post, { id: number }>({
823+
query: ({ id }) => `/post/${id}`,
824+
// use rawResponseSchema to validate *before* transformation
825+
rawResponseSchema: postSchema,
826+
// highlight-start
827+
transformResponse: (response) => ({
828+
...response,
829+
published_at: new Date(response.published_at),
830+
}),
831+
// highlight-end
832+
}),
833+
}),
834+
})
835+
```
836+
837+
:::

0 commit comments

Comments
 (0)