Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Q: how to make custom type narrowing validator (i.e. Predicate<x>)? #241

Open
leaumar opened this issue Jul 14, 2022 · 3 comments
Open

Q: how to make custom type narrowing validator (i.e. Predicate<x>)? #241

leaumar opened this issue Jul 14, 2022 · 3 comments

Comments

@leaumar
Copy link
Contributor

leaumar commented Jul 14, 2022

Colleagues and I have been wanting to make validators to assert values to be of specific subtypes, e.g. a union of specific strings, and narrow the type accordingly. We've been going over the docs here for that but it just isn't clear to us, sorry. We feel the meaning of most of the internal ow type names (Predicate, BasePredicate, Validator, ReusableValidator, Main, etc) is a little lost on us and this doesn't help us make sense of the relevant API.

type AB = 'a' | 'b';
const data = getData();
ow(data, ow.object.partialShape({
  letter: ow.string.oneOf(['a', 'b'])
}));
data.letter; // string, but we want AB

We've been trying various angles but the types never "click". Given the usual quality/DX of your libraries, we would expect there's some super simple factory function to call with a validator and generic type param, but we can't seem to cobble that together. The closest we've come is finding these APIs:

  function isAB(value: unknown): value is AB {...}

  class ABPredicate extends Predicate<AB> {
    constructor() {
      super('string');
      this.addValidator(ow.create<AB>(isAB));
    }
  }

  const ab: BasePredicate<AB> = {
    [testSymbol]: ow.string.is(isAB),
  };

The goal being:

const data: unknown;
ow(data, ow.object.partialShape({ letter: ouchAB }));
data.letter; // AB, not just string

Sorry if it's a stupid question but we'd like to stop fumbling around with it and just ask a more seasoned user or maintainer. How do we properly (e.g. a helpful failure message isn't even considered yet in our examples so far, but it should be done) and concisely (as little as possible boilerplate) make a validator to assert values and narrow the asserted type?

@leaumar
Copy link
Contributor Author

leaumar commented Jul 14, 2022

The best we now have is this

  class ABPredicate extends Predicate<AB> {
    constructor() {
      super('string');
      this.addValidator({ validator: isAB, message: (value, label) => 'TODO' });
    }
  }

and it does fulfill our purpose from what we can tell. At least the value's type is narrowed to AB after the ow() call.

But this way, the validator function isAB is given a value to assert that's already cast by ow to AB instead of the string or unknown that we'd expect, suggesting that this is either an ow API weakness or this implementation does something backward.

@sindresorhus
Copy link
Owner

ow.create is meant for creating custom validators. I don't remember whether it would solve your needs though. I also don't have time to actively maintain this package anymore (meaning, I'm happy to accept PRs, but cannot commit time to new features), so you may be better off finding a different package with a more active maintainer.

@leaumar
Copy link
Contributor Author

leaumar commented Jul 18, 2022

So I gather from you bringing that up that what we want would be a new feature, it's not really that we're missing something. Was afraid of that... I might put in the time to make a pr, I do love this lib compared to e.g. joi.

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

No branches or pull requests

2 participants