io-ts to strict validate if object has no declared property

615 views Asked by At

I'm using io-ts to do input validation for an API. I need to ensure there has no un-declared property in the requirement object.

For example, if I define the interface of request as following:

const Request = t.type({
  id: t.string,
  name: t.string
});

And if the input is as following:

const req = { 
  id: 'r1',
  name: 'req 1',
  description: 'desc' // property "description" is not declaration on Request type.
}

and then I do validating as following:

const r = Request.decode(req);

if (isLeft(r)) {
    console.log(PathReporter.report(r));
} else {
    console.log("validate success");
}

I expect output is an error for the un-declared property. but it is successed.

Have there any way to do the strict validation based on io-ts?

2

There are 2 answers

0
Colin Han On

I found a workaround for this question.
https://github.com/gcanti/io-ts/issues/322#issuecomment-513170377

import * as t from 'io-ts';
import { chain } from 'fp-ts/Either'
import { pipe } from 'fp-ts/function';

function getExcessProps(props: t.Props, r: Record<string, unknown>): string[] {
  const ex = []
  for (const k of Object.keys(r)) {
    if (!props.hasOwnProperty(k)) {
      ex.push(k)
    }
  }
  return ex
}

export function excess<C extends t.InterfaceType<t.Props>>(codec: C): C {
  const r = new t.InterfaceType(
    codec.name,
    codec.is,
    (input, c) => pipe(
      t.UnknownRecord.validate(input, c),
      chain(result => {
        const ex = getExcessProps(codec.props, result)
        return ex.length > 0
          ? t.failure(
            input,
            c,
            `Invalid value ${JSON.stringify(input)} supplied to : ${
              codec.name
            }, excess properties: ${JSON.stringify(ex)}`
          )
          : codec.validate(input, c)
      })),
    codec.encode,
    codec.props
  )
  return r as C;
}
0
ironchicken On

This is not strictly an answer to your question, but io-ts does also provide strict which will omit any properties from the input object that are not declared on the codec. (Whereas type will retain such additional properties.) strict is an alias of exact(type(...)).

Of course, this doesn't really help you with validation, but there may be related use-cases where being able to strip out additional properties is helpful.