Ensure Standardized Schema Type in Universal Restriction

Is it feasible for Zod to mandate that the type of a passed schema is restricted to a basic schema? I may be completely off track here, but I hope my intentions are clear in the provided example.

Many thanks.

import { ZodType, z } from "zod";

const baseSchema = z.object({baseString:z.string()})
const validChildSchema = baseSchema.extend({childString:z.string()})
const invalidChildSchema = z.object({childString:z.string()})

class baseClass<TSchema> // e.g. something like  "extends ZodType<typeof baseSchema>"
{}

class childClassValid extends baseClass<typeof validChildSchema>{} 

// Is there a way to modify the baseclass so this doesn't compile?
class childClassInvalid extends baseClass<typeof invalidChildSchema>{} 

Answer №1

To achieve something similar, one can restrict the "output" type of the generic parameter to match the inferred output type of the base schema.

For example:

import { z } from "zod";

const baseSchema = z.object({ baseString: z.string() });
const validChildSchema = baseSchema.extend({ childString: z.string() });
const invalidChildSchema = z.object({ childString: z.string() });

class BaseClass<TSchema extends z.ZodType<z.infer<typeof baseSchema>>> {
  constructor(public schema: TSchema) {}
}

class ChildClassValid extends BaseClass<typeof validChildSchema> {}

const v = new ChildClassValid(validChildSchema);

const out = v.schema.parse("");
console.log(out.baseString);
console.log(out.childString);

// Property 'baseString' is missing in type '{ childString: string; }' but required in type '{ baseString: string; }'.
class ChildClassInvalid extends BaseClass<typeof invalidChildSchema> {}

Typescript Playground link

Because of Typescripts structural typing, it's still possible to use schemas like this:

const anotherSchema = z.object({baseString: z.string(), foo: z.number()})

If that poses a concern, then experimenting with branded types for nominal typing may be necessary.

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

registering a back button action in Ionic2 for multiple pages

Currently, I am in the process of developing my Ionic2 app and have encountered a dilemma regarding the functionality of registerBackButtonAction. On one page, let's call it pageA, I have implemented this function and everything is functioning as exp ...

What could be causing the errors in my subscription function?

Working on an e-commerce website, I encountered errors in the "cartservice" specifically in the "checkoutFromCart()" function. The console displayed the following error: src/app/services/cart.service.ts:218:81 218 this.http.post(${this.serverUrl}ord ...

Guide to swapping out embedded objects within a TypeScript data structure

I am in need of modifying a TypeScript object by conducting a key search. It is important to note that the key may be repeated within the object, so I must ensure it belongs to the correct branch before making modifications to the corresponding object. To ...

Unable to load content from Three.js Examples library (Error loading script for "three/examples/jsm/loaders/OBJLoader2")

In my Angular application, I have a simple setup using Three.js. When I try to import the `OBJLoader2` from `three/examples/jsm/loaders/OBJLoader2`, everything works fine except when running it with the `ts_devserver`. The browser console shows an error: G ...

Using Generators with the for...of loop in Typescript

I am currently facing an issue with Typescript when trying to compile a generator-loop that works perfectly in a modern browser. The code snippet in question is: /** Should print "x= 1 y= 2" **/ function* gen() { yield [1, 2] } for (const [x, y] of gen()) ...

Step by step guide on integrating current locations in Leaflet OpenStreetMap within an Angular application

I am currently working on an Angular application that incorporates a map using Leaflet OpenStreetMap. I want to display the real-time latitude and longitude for the map, which should update based on the location. Can someone advise me on how to add the cur ...

How to declare and initialize a variable in Angular 2 using TypeScript

I'm currently working with angular 2 and I'm having trouble understanding how to set a variable. The variable _isLoading is being set in "this.observable.filter((event)" but it doesn't seem to change in the template. This is my TypeScript co ...

Service call delay not displayed on screen

I have a function that I execute in my component's ngOnInit lifecycle hook. This function calls a service to fetch data and populate an array. Once that array is filled, I then call another service method using the data from the first array to populat ...

What could be causing the TypeScript exhaustive switch check to malfunction?

How come the default case in the switch statement below does not result in an exhaustive check where 'item' is correctly identified as of type 'never'? enum Type { First, Second } interface ObjectWithType { type: Type; } c ...

TypeScript Library encounters issues when importing a specific data type

I recently integrated a library into my Next.js application to manage layouts using useState in react-grid-layout. To make this work with TypeScript, I had to install the necessary package shown below: npm install --save @types/react-grid-layout The code ...

What is the best way to incorporate vertical scrolling into a React material table?

I'm having trouble getting vertical scroll to work with my material table in React Typescript. Horizontal scroll is functioning properly for large data, but I'm stuck on implementing the vertical scroll. Here's my code: {isLoading ? ...

Issue: Unable to locate the module 'nexmo' & error TS2307: 'nexmo' module not found

Currently, I am utilizing the powerful NestJs Framework alongside typescript. My task involves incorporating two-factor authentication (SMS) using the Nexmo node library. You can find further information on their website: During the development phase, ev ...

Node.js: Handling Undefined Request Parameters

My get route is set up to receive two parameters "limit" and "page". router.get('/:limit/:page', userController.list); class UserController{ public list(req:Request, res:Response): void{ const limit:number = +req.params.limit || 25; ...

What is the procedure for invoking various functions upon the completion and loading of an iframe?

Is there a way to call different methods using JavaScript instead of the onload method, which calls the same method on loading and after loaded? I need to execute different functions - any suggestions? ...

I am encountering an issue trying to create a Docker image featuring TypeScript

I am facing an issue while trying to build a docker image using the docker build . command in my next.js app An error is being encountered Error: buildx failed with: error: failed to solve: process "/bin/sh -c yarn run build" did not complete su ...

Dealing with 'TypeError X is Not a Function' Error in Angular (TypeScript): Occurrences in Certain Scenarios and Absence in Others

Recently, I came across an odd issue in Angular 14 where a type error kept popping up. Although I managed to refactor the code and find a workaround, I'm quite intrigued as to why this issue is happening so that I can prevent it from occurring again i ...

Why is the function not being called when declaring a variable, resulting in a type error?

click here reference: const fn1 = (arg1: { key: number, })=>{ console.log(arg1) } fn1({ key: 1 }) const data = { key: 1, a: 1, } fn1(data) fn1({ key: 1, a: 1, }) more info Assistance needed: Why is ...

Context for Apollo server has not been defined

Following the upgrade to Apollo v4 and migration guide, my project was functioning properly. However, the context is now undefined. const { url } = await startStandaloneServer(server, { listen: { port: 3000 }, context: async ({ req }) => { try ...

Find a string that matches an element in a list

I currently have a list structured like this let array = [ { url: 'url1'}, { url: 'url2/test', children: [{url: 'url2/test/test'}, {url: 'url2/test2/test'}], { url: 'url3', children: [{url: & ...

Why is it necessary to include a dollar sign before interpolation in Angular?

While diving into a tutorial, I stumbled upon a piece of code that piqued my curiosity. I grasped the concept that appending a dollar sign as a suffix indicates observability, but I wonder why the dollar sign was also prefixed to this.log(`updated hero i ...