javascript - Hur tillåter jag att ett fält är odefinierat samtidigt som jag förhindrar typkonvertering med Yup?


Jag försöker validera ett objekts fält med yup.

Det här är mina krav:

  1. Fältet ska antingen vara en sträng eller odefinierat.
  2. Om det är odefinierat bör det få ett standardvärde.
  3. Om det är ett värde av någon annan typ bör det inte tvingas till en sträng. Istället bör det vara inkompatibelt och resultera i ett fel.

Jag har försökt följande hittills:

A. Följande schema förhindrar inte typkonvertering. t.ex. när värdet är ett nummer, klarar det valideringen. Jag vill dock att det ska misslyckas med valideringen.

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

B. Följande schema förhindrar typkonvertering, men det misslyckas när jag skickar ett undefined-värde. Jag vill faktiskt att värdet ska vara 'myDefaultString' om ett undefined-värde anges.

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

C. Följande schema har samma resultat som alternativ B.

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

D. Använd strict: true som en del av alternativen när du använder validateSync-metoden för att validera schemat. Återigen har detta samma resultat som B.

Skulle uppskatta all hjälp med detta, tack!

Svar #1

Yup kan uppfylla alla tre dina krav med yup.lazy* som skapar ett schema vid validering/kastningstid. Det är också mycket läsbart eftersom det använder ett lättföljt switch-uttalande.

Följande utvärderar ett värde baserat på dina villkor:

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`"); 
  }
});

Det kan då användas var som helst, inklusive ett objekts fält som i ditt exempel:

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

Sammanfatta allt:

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" }

Visa det tidigare exempel på koden på RunKit här: https://runkit.com/joematune/6138658a9113f00008292564

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

Svar #2

Jag tänkte att du kan förlänga yup-strängen på följande sätt:

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

Och sedan, ersätt StrictString() med yup.string(). Detta kommer att passa kraven.