Skip to content

Conversation

@nhagen
Copy link
Contributor

@nhagen nhagen commented Apr 2, 2021

I have a union of types, and i want to add validation to it so that if it contains any properties, they must represent the entire type that property matches with.

const A = type({ a: number(), b: number() });
const B = type({ c: number(), d: number() });

const SuperInterface = refine(union([ A. B ]), 'no partial types', val => {
  if (!is(val, A) && is(val, partial(A))) return false;
  // in the test below, `is(val, partial(b))` fails because of the A properties and
  // how partial returns a restrictive object() where extra props disqualify val
  if (!is(val, B) && is(val, partial(B))) return false;
  return true;
}

it('should throw if a partial interface is passed in addition to a full one', () => {
  // It is a SuperInterface because it matches {a,b}, however
  // it should not pass validation because {c,d} lacks {d}
  expect(() => assert({a:1, b:2, c:4}, SuperInterface)).toThrow()
  
  // Since the is(val, partial(B)) validation checks all properties of val and
  // sees more than expected, even though it is a partial of the _type interface_ it thinks
  // its something else entirely and doesn't match
})

There are other ways to do this, but it seemed idiomatic to do it this way and was surprised that it wasn't supported (plus it was simple to add)

Worth thinking about if there is/are cases this doesn't make sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant