Leverage Zod's discriminated union feature by using an enum discriminator without the need to explicitly list out all

I am currently attempting to utilize Zod schema validation for data with varying constraints depending on the value of an enumeration field (generated by Prisma). The data can take the following formats:

{ discriminatorField: "VAL1", otherField: "any string" }

{ discriminatorField: "any other allowed string besides VAL1", otherField: undefined }

It appears that this can be achieved using z.discriminatedUnion() as shown below:

const schema = z.discriminatedUnion("discriminatorField", [
   z.object({ discriminatorField: z.literal("VAL1"), otherField: z.string()}),
   z.object({ discriminatorField: z.literal("VAL2"), otherField: z.string().optional()}),
   // ... must list all possible enum values as literal conditions here?
])

While this method works, it requires listing out all potential enum values for discrimination. I attempted using z.nativeEnum(MyEnum) instead of z.literal("VAL2") in the code above, but Zod raised an error about overlapping values. Although technically correct, I had hoped it would prioritize the first matching case.

Answer №1

Here is a code snippet that defines a discriminated union schema in JavaScript using the zod library:
const schema = z.discriminatedUnion("discriminatorField", [
  z.object({ discriminatorField: z.literal("VAL1"), otherField: z.string() }),
  ...Object.values(MyEnum)
    .filter((enum) => enum !== "VAL1")
    .map((enum) =>
      z.object({
        discriminatorField: z.literal(enum),
        otherField: z.string().optional(),
      }),
    ),
]);

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

Setting form values using Angular 9

I am currently facing a challenge that I could use some assistance with. My dilemma involves integrating a new payment system, and I seem to be encountering some obstacles. Here is a snippet of what I have: options: PaystackOptions= { amount: 5000, emai ...

Combine two closely related functions into a single function

I'm dealing with two very similar functions: setEndTimesAndStartTimes(pricerules: PriceRule[], type: string) { this.endTimes = []; this.startTimes = []; pricerules.forEach(pricerule => { if (type === 'end') { ...

Struggling to connect the array of objects from the .ts file with the template (.html) in Angular

Inside this .ts file, I am populating the "mesMenus" array that I want to display in the .html file: export class MenusComponent{ mesMenus= new Array<Menu>(); constructor(private gMenuService:GestionMenuService){ this.gMenuService.onAdd ...

Can one utilize generic parameter value within a conditional type result field in Typescript?

Trying to create a versatile function type for data transformation can be a bit tricky. When dealing with a single object, it's straightforward: export type SingleObjFunction<InputDataType, OutputDataType> = (object: InputDataType) => Outpu ...

Error in TypeScript in VSCode when using the React.forwardRef function in a functional component

We are developing our component library using JavaScript instead of TypeScript. In our project's jsconfig.json file, we have set checkJs: true. All components in our library are functional and not based on class components. Whenever a component needs ...

Java identifying location details and separating them into distinct variables without utilizing regular expressions

Is there a recommended approach to breaking down an address string into separate variables for Street, City, State, and Zip code? The address may be formatted in various ways, such as comma separated or space separated. It could also include only City and ...

Manipulating arrays of objects using JavaScript

I am working with an array of objects represented as follows. data: [ {col: ['amb', 1, 2],} , {col: ['bfg', 3, 4], },] My goal is to transform this data into an array of arrays like the one shown below. [ [{a: 'amb',b: [1], c ...

Error message: The variable referenced in the subscription is not recognized outside the scope in Angular 2 when

When working with my Angular2 component, I encountered a situation where I needed to store a value from Firebase into a variable inside the constructor. Like so: this.dbAction.getDB().take(1).subscribe(data => { this.userVisitOrder = data[0][this.cur ...

Number as the Key in Typescript Record<number, string> is allowed

As a newcomer to TypeScript, I am still learning a lot and came across this code snippet that involves the Record utility types, which is quite perplexing for me. The code functions correctly in the playground environment. const data = async (name: string ...

Typescript's definition file includes imports that can result in errors

Occasionally, typescript may generate a definition file with code like the following, leading to compile errors: // issue.ts import { Observable } from 'rxjs'; class Issue { get data() { return new Observable(); } } // issue.d.ts class ...

Examine every character in the text to determine if it qualifies as a separator

Can anyone assist me with a task I'm working on? I'm trying to write a function that checks the letters of a string. I attempted to use both a for loop and a foreach loop, but I couldn't get it to work properly :( let input = this.tagsFor ...

Using the jasmine framework to create conditional test cases

Currently, I am working on Jasmine and my goal is to ensure that the test cases run only when the site's response status is okay (200). If the site fails to load, I do not want the test cases to execute. To achieve this, I am checking the site's ...

Using TypeScript to automatically determine the argument type of a function by analyzing the return type of a different function

I am working on an interface with the following structure: interface Res<R = any> { first?(): Promise<R>; second(arg: { response: R }): void; } However, I noticed that when creating a plain object based on this interface, the response ...

Using Angular to condense or manipulate an array

I am working with a JSON response that contains arrays of arrays of objects. My goal is to flatten it in an Angular way so I can display it in a Material Table. Specifically, I want to flatten the accessID and desc into a flat array like [ADPRATE, QUOCON, ...

Is there a way for me to retrieve the text generated by OpenAI in the completion response?

let gptResponse = await openai .createCompletion({ model: "davinci", prompt, max_tokens: 60, temperature: 0.9, presence_penalty: 0, frequency_penalty: 0.5, best_of: 1, n: 1, stre ...

What is the best way to eliminate hover diagnostic content in my VS Code extension?

I've implemented a VS Code extension where I've added a command to delete a diagnostic: extension.ts context.subscriptions.push( vscode.commands.registerCommand( DELETE_DIAGNOSTIC_COMMAND, () => removeDiagnostic() ) ) ...

Script - Retrieve the content of the code element

I am currently developing an extension for VS Code that will enhance Skript syntax support. One challenge I am facing is the inability to select the body of the code block. Skript syntax includes various blocks such as commands, functions, and events, eac ...

Navigating through the key type within a mapped structure

I am working with a mapped type in the following structure: type Mapped = { [Key in string]: Key }; My understanding is that this setup should only allow types where the key matches the value. However, I have found that both of the cases below are permitt ...

Angular - optional parameter in route using ngRouter

I have a question regarding using Angular (4) with the @angular/router. I want to be able to include optional parameters in a path style, but am facing some challenges. Currently, my code looks like this: { path: 'cars', component: CarComponent ...

expand attribute of foundational interface

My current situation is as follows: interface A { x: { f1(s: string): string; }; } interface B extends A { } I am looking to enhance interface A by adding a new method called f2 within the context of interface B, without redefining f1. It would ...