Jack Roper

@zcabjro/vivalidate v0.8.0 makes composition even easier

@zcabjro/vivalidate is a validation library written in typescript that focuses on being small and easy to use. Using simple primitives like string and object, you can build complex schemas and then validate incoming data at runtime while getting type declarations for free in the process.

Prior to v0.8.0, we could already get some mileage out of extracting common shapes from a schema to avoid unnecessary duplication.

const meta = v.object({
  title: v.string(),
  tags: v.array(v.string()),
  created: v.number(),
});

const post = v.object({
  id: v.string(),
  meta,
  ...otherPostFields,
});

const project = v.object({
  id: v.string(),
  meta,
  ...otherProjectFields,
});

This saves us some typing but we were lacking a way to simply extend a given schema. For example, imagine if post and project were actually almost identical except that projects contain some information about project members. Suppose also that the meta fields actually belonged on the top-level instead of being nested under meta:

const post = v.object({
  id: v.string(),
  title: v.string(),
  tags: v.array(v.string()),
  created: v.number(),
});

const project = v.object({
  id: v.string(),
  title: v.string(),
  tags: v.array(v.string()),
  created: v.number(),
  members: v.array(v.string()),
});

If we knew that the commonality between post and project was there to stay then we might resent having to duplicate the fields across both schemas. In v0.8.0, vivalidate introduces and for extending (intersecting) schemas. With it, we can shrink the above to just:

const post = v.object({
  id: v.string(),
  title: v.string(),
  tags: v.array(v.string()),
  created: v.number(),
});

const project = post.and(
  v.object({
    members: v.array(v.string()),
  }),
);

The resulting validator runs a given value through both post and the argument validator. As long as it satisfies both, then the result is typed as the intersection of the two inferred types. If either one fails to validate, then the result contains a concatenation of errors.