Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React, Yup, Formik. How to extend current schema from another schema

There are many schemes and they are combined by some identical fields. When changing the fields of one scheme, you need to change the same fields, but in other schemes. And I wanted the fields of different schemes, or the schemes themselves, to refer to or inherit one common scheme. Something like:


    import * as Yup from "yup";
    import {commonSchema} from "./common";

    export const parentSchema = Yup.object().shape({
      FirstName: Yup.string()
        .min(2, `Имя не может состоять менее чем из 2 сомволов`)
        .max(50, `Имя не может состоять более чем из 50 сомволов`)
        .required(`Поле 'Имя' обязательное для заполнения`),
      SecondName: ref(commonSchema.SecondName)
    });


    // commonSchema

    export const commonSchema = Yup.object().shape({
      SecondName: Yup.string()
        .min(2, `Отчество не может состоять менее чем из 2 сомволов`)
        .max(100, `Отчество не может состоять более чем из 100 сомволов`)
    });

In short, making changes to one general schema will not have to make changes to other schemas with the same fields.

I would like to collect all the common properties in one file. And then refer to the necessary properties from each file

like image 868
Витязи Team Avatar asked Jan 20 '26 18:01

Витязи Team


1 Answers

The closest thing to schema extension/inheritance in Yup is to use object.shape to create a new schema based on existing schema: Yup documentation

object.shape(fields: object, noSortEdges?: Array<[string, string]>): Schema

Define the keys of the object and the schemas for said keys. Note that you can chain shape method, which acts like object extends

const baseSchema = Yup.object().shape({
   id: string().isRequired(),  
  name: string().isRequired()
})

const someSchema = baseSchema.shape({
   id: number().isRequired(),
   age: number().isRequired()
})

which is equivalent to:

const someSchema = Yup.object().shape({
   id: number().isRequired(), // notice how 'id' is overridden by child schema
   name: string().isRequired(),
   age: number().isRequired()
})

Another way is to use concat(schema) to create a new schema instance by combing two schemas: Yup documentation

mixed.concat(schema: Schema): Schema Creates a new instance of the schema by combining two schemas. Only schemas of the same type can be concatenated.

const baseSchema = Yup.object().shape({
   name: string().isRequired()
})

const someSchema = baseSchema.concat(
   Yup.object().shape({
    age: number().isRequired()
}))

// someSchema will be equipped with both `name` and `age` attributes 

Please note that concat only works when two schema objects have different properties or same properties with exact same type.

like image 134
TKforce Avatar answered Jan 23 '26 09:01

TKforce