RTK Query: How to add type-safe runtime validation for server responses without writing code on a per-endpoint basis? #2576
-
Given the following code: import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
interface Post {
id: string;
title: string;
body: string;
}
export const postsApi = createApi({
baseQuery: fetchBaseQuery({
baseUrl: "https://api.example.com/",
}),
endpoints: (build) => ({
getPost: build.query<Post, string>({
query: (id) => `posts/${id}`,
}),
}),
}); RTK Query doesn't do anything to prove that the server actually returns a What I'd like is something like this (using zod for runtime validation inside import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { z } from "zod";
const Post = z.object({
id: z.string(),
title: z.string(),
body: z.string(),
});
type Post = z.infer<typeof Post>;
export const postsApi = createApi({
baseQuery: fetchBaseQuery({
baseUrl: "https://api.example.com/",
}),
endpoints: (build) => ({
getPost: build.query<Post, string>({
query: (id) => `posts/${id}`,
transformResponse: (response, _meta, _arg) => {
return Post.parse(response);
},
}),
}),
}); except that I don't want to have to specify From searching around, I found a few clues in similar discussions:
However, all of these still require extra setup on a per-endpoint basis. Is there a way to customize the base query function to generalize this pattern for all endpoints? I imagine it would require an additional argument (or perhaps both runtime and type arguments, since |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
Your request reads to me as "how to get runtime validation with only types" - and that cannot be possible. But of course you can write yourself a wrapper to make it nicer to read: export type TypeOf<T extends ZodType<any, any, any>> = T["_output"];
function validate<T extends ZodType<any, any, any>>(schema: T): TypeOf<T> {
return response => schema.parse(response)
}
// in your endpoint
endpoints: (build) => ({
getPost: build.query<Post, string>({
query: (id) => `posts/${id}`,
transformResponse: validate(Post)
}),
}), |
Beta Was this translation helpful? Give feedback.
Your request reads to me as "how to get runtime validation with only types" - and that cannot be possible.
But of course you can write yourself a wrapper to make it nicer to read: