joi icon indicating copy to clipboard operation
joi copied to clipboard

Add typings to `.extend()`

Open daweimau opened this issue 4 years ago • 7 comments

Context

  • node version: 16.13.0
  • module version: 17.5.0
  • environment (e.g. node, browser, native): node
  • used with (e.g. hapi application, another framework, standalone, ...): standalone
  • any other relevant information:

What problem are you trying to solve?

Currently .extend() is typed to return any. This completely removes all typing functions (even the base package typings) whenever Joi is extended.

const Joi = require("joi").extend('@joi/date')

// Joi is now an `any` with no typings whatsoever.

Do you have a new or modified API suggestion to solve the problem?

No- I'm not good enough with typescript to figure this one out. I tried tweaking the return type from any toJoi, but this doesn't seem to work - probably something to do with Joi being a namespace, not a class.

daweimau avatar Jan 03 '22 02:01 daweimau

I think Joi can benefit from using generics for the type declaration here. That way we can leave it to the engineer to describe the return type of whatever extensions they're extending.

A signature like

        extend<T>(...extensions: Array<Extension | ExtensionFactory>): T;

BolajiOlajide avatar Jan 07 '22 11:01 BolajiOlajide

My understanding is that Joi is not something that can be fully typed without major changes. I used a fork of Joi for a while and now I use Zod because it was made from the ground up to be Typescript compatible.

simlevesque avatar Jan 07 '22 18:01 simlevesque

The major change is coming in the next version, in the meantime, types can likely be improved to be "good enough" in some areas.

Marsup avatar Jan 07 '22 19:01 Marsup

eta on this update?

tehhowch avatar Sep 23 '22 18:09 tehhowch

There's been a change of plans since then as you can guess from the pinned issue, so unfortunately no...

Marsup avatar Sep 23 '22 18:09 Marsup

I noticed that there are some missing related typings on extension's validate https://github.com/hapijs/joi/blob/d7afcd567bab64a79a4d38332c5b169c5f0e3bf6/lib/index.d.ts#L2001

  1. seems like this could be informed by the documentation: to be e.g.
  validate<T>?(value: T, helpers: CustomHelpers<T>): { value: T } | { errors: ErrorReport | ErrorReport[] };
  validate<T>?(value: T[], helpers: CustomHelpers<T>): { value: T[] } | { errors: ErrorReport | ErrorReport[] };

Since it will be invoked with a particular type of value (which may be an array).

  1. the CustomHelpers type passed in is missing the errorsArray property which is called out loudly in the documentation for extensions

Validation helpers

  • original: The original value passed untouched to validate().
  • prefs: The prepared validation options.
  • schema: The reference to the current schema. Useful if you need to use any of the Advanced functions.
  • state: The current validation state. See Validation state.
  • error: A function with signature function (code, local, localState = currentState) {} similar to $_createError() but with the current value, validation options, current state passed where: code: The error code. local: Local context used to interpolate the message. localState: The localized state.
  • errorsArray: A function that creates an array that can be recognised by Joi as a valid error array. Note that using a native JS array can cause Joi to output incorrect results.
  • warn: TODO
  • message: TODO

https://github.com/hapijs/joi/blob/d7afcd567bab64a79a4d38332c5b169c5f0e3bf6/lib/validator.js#L200-L209

Addressing these two seem like small fixes that won't resolve the larger issue of what extend returns, but which would certainly help ease the process of implementing extensions correctly somewhat

tehhowch avatar Sep 23 '22 18:09 tehhowch

  1. any kind of makes sense if you consider that you're not forced in any way to return the same type as what was passed, it's unusual and discouraged as you'll likely run into problems if you chain other validators, but it's possible
  2. I'd certainly take a PR for that, this pattern is both missing typings and documentation

Marsup avatar Oct 11 '22 14:10 Marsup