Guide on creating a zodiac validator that specifically handles properties with inferred types of number or undefined

There are some predefined definitions for an API (with types generated using protocol buffers). I prefer not to modify these.

One of the types, which we'll refer to as SomeInterfaceOutOfMyControl, includes a property that is a union type of undefined. Here's how it looks:

interface SomeInterfaceOutOfMyControl {
    someProperty: number | undefined
}

function someFuncOutOfMyControl(obj: SomeInterfaceOutOfMyControl) {}

I am attempting to create a validator to ensure that the data adheres to the correct format. For this purpose, I am utilizing zod.

const validator = z.object({
    someProperty: z.optional(z.number()),
})

However, the TypeScript compiler seems to be confused about the fact that number | undefined is essentially the same as an optional property. Hence, I encounter this compiler error:

error TS2322: Type '{ someProperty?: number | undefined; }' is not assignable to type 'SomeInterfaceOutOfMyControl'. Property 'someProperty' is optional in type '{ someProperty?: number | undefined; }' but required in type 'SomeInterfaceOutOfMyControl'.

const object: SomeInterfaceOutOfMyControl = validator.parse(someData)

const validator = z.object({
    someProperty: z.union([z.number(), z.undefined()]),
})
const someData = {} as any
const object = validator.parse(someData)

someFuncOutOfMyControl(object)
// Error on the line above:
// Argument of type '{ someProperty?: number | undefined; }' is not assignable to parameter of type 'SomeInterfaceOutOfMyControl'.
// Property 'someProperty' is optional in type '{ someProperty?: number | undefined; }' but required in type 'SomeInterfaceOutOfMyControl'.

How can I adjust the zod validation so that the inferred type aligns with the interface correctly? In other words, how do I create a validator for this?:

interface SomeInterfaceOutOfMyControl {
    someProperty: number | undefined
}

I attempted using a union:

const validator = z.object({
    someProperty: z.union([z.number(), z.undefined()]),
})

However, the outcome remains the same...

Answer №1

Here's a creative workaround I came up with to address the issue at hand. It may not be directly applicable to your specific scenario, but I believe it's worth sharing.

Given the limitation of not being able to modify SomeInterfaceOutOfMyControl,

You can extend it and define optional fields using Partial. Here's how:

interface SomeInterfaceOutOfMyControl {
  someProperty: number | undefined;
}

type MyInterface = Partial<SomeInterfaceOutOfMyControl>;

const validator: z.ZodType<MyInterface> = z.object({
  someProperty: z.union([z.number(), z.undefined()]),
});

const someData = {} as any;

const object: MyInterface = validator.parse(someData);

Answer №2

Are you considering making a modification to the schema as a potential solution:

import {z} from "zod"
interface SomeInterfaceOutOfMyControl {
    someProperty: number | undefined
}

function someFuncOutOfMyControl(obj: SomeInterfaceOutOfMyControl) {}

const validator = z.object({
    someProperty: z.number().optional(),
}).transform(o => ({...o, someProperty: o.someProperty }))

const someData = {} as unknown
const object: SomeInterfaceOutOfMyControl = validator.parse(someData)
someFuncOutOfMyControl(object)

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

How can Firebase and Ionic be used to customize the password reset template for sending verification emails and more?

I'm facing an issue with firebase's auth templates not supporting my native language. Is there a way to customize the password reset template to also handle verification and email address change emails? ...

Acquire keys from a different residence

Currently, I am working on a React component that accepts data through props and I aim to implement safe property access. I have experimented with the following: type Props = { items?: any[]; // uncertain about using type "any" bindValue?: keyof Prop ...

Managing Observable<Person[]> in ng-bootstrap typeahead instead of Observable<string[]>: a complete guide

I'm new to Angular/Typescript and have a question. I recently tried out the example from Wikipedia in ng-bootstrap typeahead. Instead of using the Wikipedia call, I decided to use a custom REST service that has the following GET endpoint: GET /pers ...

Incorrectly asserting the data type of a union

I am having trouble getting the type assertion to work in this specific scenario. Here is a Playground Link type Letter = "A" | "B" type Useless = {} type Container<T> = Useless | { type: "container" ...

Finding the number of elements in a FirebaseListObservable involves accessing the `length` property

One of the tasks in my Angular 2 application involves retrieving data from a Firebase database and storing it in a FirebaseListObservable. I have a method called getStatus that is supposed to determine the number of elements in this FirebaseListObservable. ...

Code coverage analysis in a node.js TypeScript project consistently shows no coverage metrics

I'm currently working on a backend TypeScript project where I'm aiming to obtain coverage reports for unit test cases. However, Jest is returning empty coverage reports both in the terminal and in the HTML report, with no information provided. Ev ...

Ionic: Fixed button located at the bottom of a specific ion-slide

I've been creating a series of slides with questions, and the final slide serves as a summary of the previously answered questions. I want to ensure that the submit button is always visible at the bottom of this last slide. However, I've encounte ...

What are the properties used in functional components of React?

Seeking guidance on passing React component props to another component: interface IMyComponent { props: Props<any> } const MyComponent: FC = ({ props }) => { } Previously, I attempted to utilize the React.Props type after consulting this que ...

JavaScript alert box

I'm fairly new to the world of web development, with knowledge in CSS & HTML and currently learning TypeScript. I'm attempting to create a message icon that opens and closes a notifications bar. Here's where I'm at so far: document.getE ...

The struggle of accessing child components using ViewChild in Angular

I am facing an issue with a dialog box that is supposed to display a child component separately. Below is the code for the child component: @Component({ selector: 'userEdit', templateUrl: './edituser.component.html', styleUrls: [ ...

Is there a way to receive a comprehensive report in case the deletion process encounters an error?

Currently, I am performing a delete operation with a filter based on 2 fields: const query = await Flow.deleteOne({ _id: flowId, permissions: currentUser!.id, }); After executing the delete operation, I inspect the query object to determine its su ...

How can methods from another class be accessed in a TypeScript constructor?

I need to access a method from UserModel within the constructor of my UserLogic class. How can I achieve this? import { UserModel, ItUser } from '../../models/user.model'; export class UserLogic { public user: ItUser; constructor() { ...

Please explain the purpose of the httponly ss-tok bearerToken cookie in ServiceStack Authentication

While I comprehend the importance of implementing an httponly flag in the Set-Cookie Response header to enhance security and prevent XSS attacks, there is one aspect that remains unclear to me. Specifically, I am unsure about the purpose of the "ss-tok" co ...

Accessing JSON data stored locally and initializing it into a TypeScript variable within a React application

I'm new to working with JSON arrays and I'm facing a challenge. I am looking for a way to load data from a JSON file into a Typescript variable so that I can perform a specific operation that involves arrays. However, I'm unsure of how to ac ...

The Authorization header in POST and PATCH fetch requests is stripped by Typescript

I have developed an API in C# that utilizes JWT tokens for authorization. On the frontend, I store these tokens in local storage and retrieve them when making a request. GET or DELETE requests work seamlessly, as I can verify through console.log() that t ...

Encountering issue with FullCalendar and Angular 11: Error reading property '__k' of null

I am currently utilizing the Full Calendar plugin with Angular 11 but have encountered an error message stating "Cannot read property '__k' of null". It appears to be occurring when the calendar.render() function is called, and I'm strugglin ...

Showing elapsed time similar to YouTube in an Angular 8 application

Currently, I am developing an Angular application to replicate certain features found on YouTube by utilizing data fetched from an API. This API provides video timestamps in a string format Each timestamp follows this structure : YYYY-MM-DDTHH:MM:SS For ...

Guide to locating a particular node within an array of nested objects by utilizing the object

Dealing with an array of nested objects, the goal is to compare values with a flat array and update the property matchFound. If the parent's matchFound is true, then all its children should inherit this value. treeData = [{ field: 'make&a ...

Error with Angular 2 observables in TypeScript

When a user types a search string into an input field, I want to implement a debounce feature that waits for at least 300 milliseconds before making a request to the _heroService using HTTP. Only modified search values should be sent to the service (distin ...

Can you input a string into a generic in TypeScript and subsequently utilize it as a type/interface key?

I had high hopes for achieving this, but unfortunately it's a no-go: type MyType< T extends {}, K extends string = 'keyName' > = T & { [K]: { value: string } }; The error states that a computed property name in a typ ...