Search code examples
typescriptzod

How to implement a generic fetch function that validates the query parameter and json result using zod


I'm trying to implement a generic fetch function that abstracts away the validation of the query parameters and the json return using zod schemas. I came up with the following prototype but cannot seem to figure out how to type the zod schema parameter:

import {z} from 'zod';

const zodFetch = async <TQuerySchema, TResponseSchema>(url: string, querySchema: TQuerySchema, query: z.infer<typeof TQuerySchema>, responseSchema: TResponseSchema): Promise<z.infer<typeof TResponseSchema>> => {
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'content-type': 'application/json;charset=UTF-8',
        },
        body: JSON.stringify({
            query: querySchema.parse(query),
        }),
    });

    return responseSchema.parse(await response.json());
};


const test = async () => {
    const fooSchema = z.number();
    const barSchema = z.string();

    const response = await zodFetch('https://foobar', fooSchema, 1, barSchema);

    console.log(response);
};

void test();

Solution

  • Add generic constraints and remove typeof since it's already a type:

    const zodFetch = async <TQuerySchema extends z.Schema, TResponseSchema extends z.Schema>(url: string, querySchema: TQuerySchema, query: z.infer<TQuerySchema>, responseSchema: TResponseSchema): Promise<z.infer<TResponseSchema>> => {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'content-type': 'application/json;charset=UTF-8',
            },
            body: JSON.stringify({
                query: querySchema.parse(query),
            }),
        });
    
        return responseSchema.parse(await response.json());
    };
    

    Playground