Step-by-step guide on developing a fresh zod schema while automatically determining its type

Is there a way to reassign the value of an object using TypeScript?

I have an interface defined as follows:

interface Root {
    userId: number;
    id: number;
    title: string;
    completed: boolean;
}

I am familiar with creating a zod schema from this interface like so:

const zRoot: z.ZodType<Root> = z.object({
    userId: z.number(),
    id: z.number(),
    title: z.string(),
    completed: z.boolean(),
});

However, I am unsure how to create a schema that types like this:

type RootObjectArray = {
    [F in keyof Root]: Root[F][];
};

Answer №1

This specific demonstration showcases the utilization of a validating schema for the RootObjectArray that has been provided. It also includes evidence that it aligns with the specified requirements (you can hover over RootMatches and RootObjectArrayMatches to verify). The script has been rigorously evaluated only through testing in the sandbox environment.

import { z, ZodObject, ZodArray, ZodRawShape } from "zod";

export function safeKeys<Lookup extends { [k in string]: unknown }>(
  lookup: Lookup
) {
  return Object.keys(lookup) as (keyof Lookup)[];
}

export function mapFrom<Map extends object>(
  keys: readonly (keyof Map)[],
  mapFn: <Key extends keyof Map>(key: Key) => Map[Key]
) {
  return Object.fromEntries(keys.map((key) => [key, mapFn(key)])) as {
    [K in keyof Map]: Map[K];
  };
}

interface Root {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

type RootObjectArray = {
  [F in keyof Root]: Root[F][];
};

const zRoot = z.object({
  userId: z.number(),
  id: z.number(),
  title: z.string(),
  completed: z.boolean(),
});

function toArraySchema<Shape extends ZodRawShape>(schema: ZodObject<Shape>) {
  const shape: Shape = schema.shape;
  return mapFrom<{ [K in keyof Shape]: ZodArray<Shape[K]> }>(
    safeKeys(shape),
    (key) => z.array(shape[key])
  );
}

const zRootObjectArray = z.object(toArraySchema(zRoot));

type ZodRoot = z.infer<typeof zRoot>;
type ZodRootObjectArray = z.infer<typeof zRootObjectArray>

type Equivalent<X, Y> = X extends Y ? (Y extends X ? true : false) : false;

type RootMatches = Equivalent<Root, ZodRoot>;
type RootObjectArrayMatches = Equivalent<RootObjectArray, ZodRootObjectArray>;

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

Tips to successfully save and retrieve a state from storage

I've encountered a challenge while working on my Angular 14 and Ionic 6 app. I want to implement a "Welcome" screen that only appears the first time a user opens the app, and never again after that. I'm struggling to figure out how to save the s ...

Efficiently storing a newly shuffled list of tasks into the db.json file using Angular

This is the content of my db.json document { "tasks": [ { "id": 1, "text": "Doctors Appointment", "day": "May 5th at 2:30pm", "reminder": true }, { ...

In order to view current data on the chart, I need to use array.slice() in the markup which unfortunately disables the ability to select specific points. Check out the Stackbl

When viewing the line chart, there is a select event that allows for the selection of points and legend items. The line chart includes an activeElements input property that requires an array of the active elements to be passed in. One interesting thing to ...

Issue with rendering HTML tags when replacing strings within Ionic 2 and Angular 2

I am currently working with an array of content in my JSON that includes URLs as plain text. My goal is to detect these text URLs and convert them into actual clickable links. However, I'm facing an issue where even though the URL is properly replaced ...

It appears that TypeScript is generating incorrect 'this' code without giving any warning

I seem to be facing some resistance filing a feature request related to this on GitHub issues, so I'll give it a shot here. Here is the code snippet that caused me trouble: export class Example { readonly myOtherElement: HTMLElement; public ...

Calculating the minimum value of a number in Angular 8

I attempted to convert a decimal number to a whole number and encountered an issue. When using the angular pipe method {{myNumber | number: '1.0-0.'}}, it provides a rounded off value instead of the floor value. For example, with number = 3.8, ...

The unit test is not passing due to inconsistencies between the mock data generated in the constructors and the original mock data

Currently, I am delving into the world of unit testing and have created a test to work on. Here is what I have so far: const EXEPECTED: MergedFood = { id: '1', name: 'test mergedFood', ingredients: { '2': ...

Creating dynamic key objects in TypeScript with index signatures: A beginner's guide

How can the code be optimized to automatically initialize a new product type without adding extra lines of code? Failure to initialize the variable results in a syntax error. enum ProductType { PC = 'pc', LAPTOP = 'laptop', TV ...

Guide to extracting the JSON array from a JSON object with Angular

In my angular application, I have made a call to the API and retrieved a JSON object in the console. However, within this JSON object, there are both strings and arrays. My task now is to extract and parse the array from the object in the console. The JSO ...

What is the reason `addEventListener` does not work with a class method?

Recently, I discovered that the listener passed to addEventListener can actually be an object with a handleEvent function instead of just a callback function (here). However, I encountered an issue when trying to use handleEvent as a class method: class F ...

Can anyone provide guidance on incorporating lodash into an Ionic 2 project?

Recently, I began diving into a new project that involves Ionic 2. TypeScript is still fairly new to me, and I've been brainstorming ways to integrate lodash into my project. Have any of you tackled this before and can offer guidance on how to achiev ...

Guide on retrieving a nested JSON array to extract a comprehensive list of values from every parameter within every object

A JSON file with various data points is available: { "success": true, "dataPoints": [{ "count_id": 4, "avg_temperature": 2817, "startTime": "00:00:00", "endTime": "00:19:59.999" }, ... I am trying to extract all the values of & ...

Utilizing the axios create method: troubleshooting and best practices

I am attempting to use the axios library in my Next.js app (written in TypeScript) to access a public API for retrieving IP addresses from . In my index.ts file, I have the following code: import axios from "axios"; export const ipApi = axios.cr ...

Jasmine's await function often leads to variables remaining undefined

When testing a function, I encountered an issue where a variable is created and assigned a value, but the payload constant always remains undefined. campaigns-card.component.ts async ngOnInit() { const { uid } = await this.auth.currentUser const { ...

Is it possible to enter NaN in Vue3?

Is there a way to handle NaN values and keep a field blank instead when calculating margins with a formula? https://i.stack.imgur.com/JvIRQ.png Template <form> <div class="row"> <div class="mb-3 col-sm ...

Error! Element not found in cloned iframe #2460, promise unhandled

Can you help me troubleshoot this issue? This is the code I'm working with: const section = document.createElement("section"); const myHTMLCode = "<p>Greetings</p>"; section.insertAdjacentHTML("afterbegin", my ...

Is it possible for a redis client to function without having a redis datastore installed?

Currently in my node web server, I am utilizing the npm module known as redis. Upon executing my code... const client = redis.createClient(); client.on("error", function (err) { console.log("Error " + err); }); client.hmset(["key", "test keys 1", "t ...

"Troubleshooting Typecscript and Angular: Dealing with mismatched argument

How can I resolve this Angular error: (response: HttpResponse<User>) => { which results in the following error message: Argument of type '(response: HttpResponse<User>) => void' is not assignable to parameter of type '(val ...

What is the best approach for setting up a global pipe that can be utilized across various modules?

One of my Angular projects includes a custom pipe called CurrConvertPipe. import {Pipe, PipeTransform} from '@angular/core'; import {LocalStorageService} from './local-storage'; @Pipe({name: 'currConvert', pure: false}) expor ...

Implement a query in Mongoose using the Schema First methodology within NestJS

In the beginning, I must mention that this query bears resemblance to this one which points to this particular question. My inquiry mirrors the second link with a noticeable distinction. I am endeavoring to expand a class produced by NestJS which delineate ...