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

Type declaration for messages option of any.validate() inconsistent with the documentation and actual code #2720

Closed
kmbt opened this issue Jan 8, 2022 · 6 comments
Assignees
Labels
types TypeScript type definitions
Milestone

Comments

@kmbt
Copy link

kmbt commented Jan 8, 2022

Context

  • node version: v16.13.1
  • module version with issue: 17.5.0
  • last module version without issue: ?
  • environment (e.g. node, browser, native): node
  • used with (e.g. hapi application, another framework, standalone, ...): standalone
  • any other relevant information:

What are you trying to achieve or the steps to reproduce?

I am trying to supply localized error messages as documented here: https://github.com/sideway/joi/blob/master/API.md#anyvalidatevalue-options

The documentation for options.errors.language states that the messages object is a 'two-dimensional' object:

The value is matched against keys at the root of the messages object, and then the error code as a child key of that

, thus I try to use schema.validate() the following way:

import Joi, { LanguageMessages } from "joi";

const validationMessages = {
  'en': {
    'string.empty': 'XYZ',
  }
}

const schema = Joi.object({
  key: Joi.string()
})

schema.validate({}, {
  errors: {
    language: 'en'
  },
  messages: validationMessages
})

What was the result you got?

A typescript error on messages option:

Type '{ en: { 'string.empty': string; }; }' is not assignable to type 'LanguageMessages'.
  Property ''en'' is incompatible with index signature.
    Type '{ 'string.empty': string; }' is not assignable to type 'string'.ts(2322)

Looking into the library code I have found that the type for messages given here:
https://github.com/sideway/joi/blob/b4dbd59371be9d0fbbaa5f561d5aef929028ad99/lib/index.d.ts#L181-L190
is LanguageMessages which is defined here:
https://github.com/sideway/joi/blob/b4dbd59371be9d0fbbaa5f561d5aef929028ad99/lib/index.d.ts#L29

, which is just a flat object.

What result did you expect?

I would expect, that the required type for messages is declared as one of the following:

  1. Record<string, string | Record<string, string>>
  2. Record<string, Record<string, string>>
  3. Record<string, string> | Record<string, Record<string, string>>

Option 1. seems to most accurately describe the data shape actually accepted as the messages option. It actually seems possible to provide a flat object with just error keys or a mixed one, as such:

const validationMessages : T = {
  'es': {
    'string.empty': 'XYZ',
  },
  'pl': {
    'string.empty': 'KLM',
  },
  'string.empty': 'PQR'
}

, while Option 2. reflects the documentation for validate() best.

@eladchen
Copy link

eladchen commented Jan 21, 2022

Exactly! run into this myself.

@atresca-globant
Copy link

Having the same problem

@calbertts
Copy link

Is there any solution to this issue?
I'm using typescript and I've found your blog entry but I cannot make it work because the compilation issue.

@calbertts
Copy link

Is there any solution to this issue? I'm using typescript and I've found your blog entry but I cannot make it work because the compilation issue.

If anyone else has this doubt, this is the way:

const validationOptions = { ... }
const validate = schema.validate(payload, validationOptions as unknown as Joi.ValidationOptions);

@jacobkapitein
Copy link
Contributor

Can confirm this is still an issue. It was really annoying. Found out the type declaration was wrong, because language keys are supported in this function:

exports.template = function (value, messages, code, state, prefs) {

Type declaration for the messages schema can be found here:
type LanguageMessages = Record<string, string>;

The most accurate type would indeed be Record<string, string | Record<string, string>>.

@jacobkapitein
Copy link
Contributor

I created a quick patch with ts-patch.

Use this to fix any errors you might encounter:

diff --git a/node_modules/joi/lib/index.d.ts b/node_modules/joi/lib/index.d.ts
index da367a9..3ed262e 100644
--- a/node_modules/joi/lib/index.d.ts
+++ b/node_modules/joi/lib/index.d.ts
@@ -26,7 +26,7 @@ declare namespace Joi {
 
     type BasicType = boolean | number | string | any[] | object | null;
 
-    type LanguageMessages = Record<string, string>;
+    type LanguageMessages = Record<string, string | Record<string, string>>;
 
     type PresenceMode = 'optional' | 'required' | 'forbidden';

@Marsup Marsup added this to the 17.11.1 milestone Jan 17, 2024
@Marsup Marsup added the types TypeScript type definitions label Jan 17, 2024
@Marsup Marsup self-assigned this Jan 17, 2024
@Marsup Marsup closed this as completed Jan 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
types TypeScript type definitions
Projects
None yet
Development

No branches or pull requests

6 participants