Búsqueda de sitios web

javascript - ¿Cómo permito que un campo sea indefinido mientras desactivo la coerción de tipos usando Yup?


Estoy intentando validar el campo de un objeto usando yup.

Estos son mis requisitos:

  1. El campo debe ser una cadena o indefinido.
  2. Si está indefinido, se le debe dar un valor por defecto.
  3. Si es un valor de algún otro tipo, no debe ser convertido en una cadena. En cambio, debe ser incompatible y debería resultar en un error.

He intentado lo siguiente hasta ahora:

A. El siguiente esquema no previene la coerción de tipos. Por ejemplo, cuando el valor es un número, pasa la validación. Sin embargo, quiero que falle la validación.

const schema = yup.object().shape({
  myField: yup.string().default('myDefaultString')
});

B. El siguiente esquema previene la coerción de tipos, pero falla cuando paso un valor indefinido. En realidad, quiero que el valor sea 'myDefaultString' si se proporciona un valor indefinido.

const schema = yup.object().shape({
  myField: yup.string().strict(true).default('myDefaultString')
});

C. El siguiente esquema tiene el mismo resultado que la opción B.

const schema = yup.object().shape({
  myField: yup.string().strict(true).notRequired().default('myDefaultString')
});

D. Use strict: true como parte de las opciones al usar el método validateSync para validar el esquema. Nuevamente, esto tiene el mismo resultado que B.

¡Agradecería cualquier ayuda con esto, gracias!

Respuesta #1

Yup es capaz de satisfacer los tres requisitos utilizando yup.lazy*, que crea un esquema en el momento de la validación/casteo. También es muy legible ya que utiliza una declaración switch fácil de seguir.

Lo siguiente evalúa un valor basado en tus condiciones:

const StringOrUndefinedSchema = yup.lazy((value) => {
  switch (typeof value) {
    case 'undefined':
      return yup.string().default('myDefaultString');
    case 'string':
      return yup.string().strict();
    default:
      throw new yup.ValidationError("Value must be a string or `undefined`"); 
  }
});

Luego puede usarse en cualquier lugar, incluido el campo de un objeto como en tu ejemplo:

const ObjectWithFieldSchema = yup.object({
  myField: StringOrUndefinedSchema,
});

Uniéndolo todo:

const yup = require("yup");

const StringOrUndefinedSchema = yup.lazy((value) => {
  switch (typeof value) {
    case 'undefined':
      return yup.string().default('myDefaultString');
    case 'string':
      return yup.string();
    default:
      throw new yup.ValidationError("Value must be a string or `undefined`"); 
  }
});

const ObjectWithFieldSchema = yup.object({
  myField: StringOrUndefinedSchema,
});

const iWillDefault = await ObjectWithFieldSchema.validate({ });
const iWillBeStrict = await ObjectWithFieldSchema.validate({ myField: "I am a string" });

console.log(iWillDefault); // { myField: "myDefaultString" }
console.log(iWillBeStrict); // { myField: "I am a string" }

Vea el código de ejemplo anterior en RunKit aquí: https://runkit.com/joematune/6138658a9113f00008292564

  • Yup.lazy - https://github.com/jquense/yup#yuplazyvalue-any--schema-lazy

Respuesta #2

Supuse que puedes extender la cadena yup de la siguiente manera:

class StrictString extends yup.string {
  constructor() {
    super();
    transforms = []; // remove the default type coercion transforms
  }
}

Y luego, reemplaza StrictString() con yup.string(). Esto cumplirá con los requisitos.