Zod: Formulate a database structure by utilizing a pre-established data model

I need to validate an endpoint that requires a parameter method, following the Axios type Method.

Is there a way to use Zod to create a schema that ensures the value matches the type Schema?

import { Method } from 'axios';

const Schema = zod.object({
  method: zod.someHowUseTheTypeFrom(Method),
});

The list of types for Method in the Axios package is as follows:

export type Method =
  | 'get' | 'GET'
  | 'delete' | 'DELETE'
  | 'head' | 'HEAD'
  | 'options' | 'OPTIONS'
  | 'post' | 'POST'
  | 'put' | 'PUT'
  | 'patch' | 'PATCH'
  | 'purge' | 'PURGE'
  | 'link' | 'LINK'
  | 'unlink' | 'UNLINK'

Answer №1

After reviewing your feedback, it seems like you are aiming to ensure that your schema aligns with the Method type from axios. Here is a suggestion on how you can achieve this:

import { z } from 'zod';
import type { Method } from 'axios';

const methods: z.ZodType<Method> = z.enum(['get', 'GET', ...]);

This approach will enforce that the schema on the right side of the expression can only parse valid axios Method results. However, achieving more than this may be challenging unless axios also provides an array containing the corresponding method strings for the Method type.

The original concept you were exploring, such as using z.something(<type here>), won't work due to zod utilizing actual runtime objects, and types like Method not existing at runtime. If axios supplied an array of methods, then it would be feasible to generate your methods schema based on that (with potential type casting).

One limitation of the initial approach is evident when defining the schema with a single value like so:

const methods z.ZodType<Method> = z.enum(['get']);

This is permitted in TypeScript because of how types function. Even though the schema only accepts 'get', it can still be assigned due to the subtype relationship with the larger union type defined by Method.

Considering these factors, another option could involve redeclaring all Method values to create a schema that encompasses all possibilities:

import { z } from "zod";
import { Method } from "axios";

const METHOD_MAP: { [K in Method]: null } = {
  get: null,
  GET: null,
  delete: null,
  DELETE: null,
  // list continues...
};

const METHODS = (Object.keys(METHOD_MAP) as unknown) as readonly [
  Method,
  ...Method[]
];
const methods: z.ZodType<Method> = z.enum(METHODS);

The type assertion for METHODS is safe since METHOD_MAP is internal, preventing any missing Method values. As a result, the compiled schema guarantees parsing of all Method values while adhering to compile-time constraints.

Answer №2

After some experimentation, I've discovered that utilizing the z.custom<ExistingType>() method is effective for solving this particular issue.

[Updated] As pointed out by @esteban-toress, it's necessary to include a validation function at the end like so:

z.custom<ExistingType>((value) => //do something & return a boolean)
. Simply using z.custom<ExistingType>() on its own will only result in a type of ZodAny, which permits any value.

[Updated] While this approach may be suitable for type inferences to meet Typescript requirements, I would advise against using it for Zod validation given the aforementioned behavior.

For more information, refer to the documentation:

Answer №3

To utilize the type directly, you can implement the following approach:

const options = ['option1', 'option2', ...] as const;

export type Selection = (typeof options)[number];

customFunction(options);

This method provides you with the advantage of having the selection options stored in a usable value (array) while also maintaining the desired type.

Answer №4

If you need to convert your typescript type to a zod schema, consider using ts-to-zod.

Answer №5

Do you already have a data type defined in an ORM schema, GraphQL generated code, or similar source, and now you want to incorporate Zod validation? Here's a method that has worked for me:

export type InferZodMap<T extends abstract new (...args: any) => any> = {
    [k in keyof Partial<InstanceType<T>>]?: unknown;
};


// Usage example:

type User {
    email: string;
}

const UserInsertValidation = z.object({
  email: z.string(),
} satisfies InferZodMap<User>);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The specified type 'undefined' cannot be assigned to the type '"default" | "red" | "green" | "blue"

I am currently developing an app using React and TypeScript. Can someone help me troubleshoot and resolve the error message below? import { styled } from "linaria/react"; type Color = { color: "default" | "red" | "gree ...

Download pictures from swift into typescript with the help of share extensions

Currently, I am working on setting up Share Extensions in my ionic3 application. To begin with, I followed these steps: Firstly, I built the app and then launched it in Xcode. After that, I added a Share Extension by navigating to File -> New -> Ta ...

What is the process of encapsulating a callback function within another callback function and invoking it from there?

Here is the code snippet I am working with: var me = this; gapi.auth.authorize({ client_id: client, scope: scope, immediate: true }, function (authResult: any) { if (authResult && !authResult.error) { me ...

Angular: Real-time monitoring of changes in the attribute value of a modal dialog and applying or removing a class to the element

I cannot seem to figure out a solution for the following issue: I have two sibling div elements. The second one contains a button that triggers a modal dialog with a dark overlay. However, in my case, the first div appears on top of the modal dialog due to ...

Is it feasible to bring in a Typescript file into an active ts-node REPL session?

I want to experiment with some Typescript code that I have written. Currently, I usually run ts-node my-file-name.ts to test it out. But I am interested in making this process more interactive, similar to the Python REPL where you can import modules and ...

How can I dynamically add a named property to a class during runtime and ensure that TypeScript recognizes it?

Within my coding project, I have implemented a decorator that alters a class by adding additional methods to it, specifically in the class A. However, when utilizing an instance of this class, the added methods do not show up in the autocomplete feature. A ...

How can I provide type annotations for search parameters in Next.js 13?

Within my Next.js 13 project, I've implemented a login form structure as outlined below: "use client"; import * as React from "react"; import { zodResolver } from "@hookform/resolvers/zod"; import { signIn } from "n ...

How to share data between two different components in Angular 6

I have a component called course-detail that fetches data (referred to as course) from my backend application. I want to pass this data to another component named course-play, which is not directly related to the course-detail component. The goal is to dis ...

How can you reposition a component within the dom using Angular?

Just started learning Angular, so I'm hoping this question is simple :) Without getting too specific with code, I could use some guidance to point me in the right direction. I'm currently developing a small shopping list application. The idea i ...

What is the best way to integrate retrieved data into Next.js with TypeScript?

Hello everyone! I recently started working with Next.js and TypeScript. Currently, I'm attempting to use the map() function on data fetched from JsonPlaceholder API. Here is my implementation for getStaticProps: export const getStaticProps: GetStatic ...

Upcoming 13.4 Error: NEXT_REDIRECT detected in API routes

Here is the code snippet from my /app/api/auth/route.ts file: import { redirect } from 'next/navigation'; export async function GET(req: Request) { try { redirect('/dashboard'); } catch (error) { console.log(error); ...

Move your cursor over a specific element to trigger an effect on another element that is not directly next to or related to it

In my current project, which is built with Angular, I am looking for a way to achieve a specific effect without using jQuery. Specifically, I would like the text inside a div element with the class title to have underline styling when hovering over an im ...

The usage of the import statement outside a module is not permitted in a serverless Node application

I am currently in the process of migrating a serverless AWS lambda microservices API to TypeScript. My goal is to retain the existing JavaScript files while incorporating more TypeScript files as we progress. However, I am encountering difficulties with co ...

Make sure to refresh the state of the store whenever there is a change detected in the input

I am experiencing an input delay problem when trying to update the state of a zustand variable in the onChange event. const BuildOrder = (props: { setOpen: Function }) => { const { almacenes, isLoadingAlmacenes } = useGetAlmacenes(); const { article ...

Sorting through a collection of objects using various criteria in typeScript

Hello team, I have an array of objects that looks like this: data = [ { name: "Pork", category: "Food", subcategory: "Meat" }, { name: "Pepper", category: "Food", subcategory: "Vegetables" }, ...

"Activate the mat-checkbox based on the outcome of a certain process

I'm working with a mat-checkbox that triggers a mat-dialog when clicked. If the user clicks "confirm" in the dialog, I want the checkbox to be checked. If they click "cancel", I want it to remain unchecked. How can I achieve this? Below is the method ...

Trouble with the page not updating after creating or updating a task

Currently, I am developing a project using Next.js along with Drizzle ORM. The main functionality involves creating and updating tasks. However, after submitting the task form, the page navigates back to the homepage, but the newly created/updated task doe ...

I am experiencing difficulties with implementing Angular material components in my project

I recently encountered an issue while trying to integrate angular material into my project. Despite importing the MatFormFieldModule, I received the following error: ERROR in src/app/login/components/login/login.component.html:2:1 - error NG8001: &apo ...

Is it Mission Impossible to Combine NodeJs, Restify, SQL Server, TypeScript, and IIS?

Starting a Rest API project using NodeJS with Restify on a Windows environment (local server with IIS and SQLServer) while also using Typescript may seem like a difficult task. Is it an impossible mission? Does anyone have any helpful guides, documentatio ...

The value of 'this.selectedNodes' does not support iteration and is causing a

I am currently utilizing v-network-graphs to generate graphs in the front end with Vue. I have set up my data like this: data(){ return{ test: test_data, nodes:{}, edges:{}, nextNodeIndex: Number, selectedNodes: ref<st ...