hapijs / hapijs/joi

Add support for Typescript's exactOptionalPropertyTypes setting

Open
#2,943 0 comments 0 reactions 0 assignees View on GitHub
feature
Dominant language
JavaScript
Stars
21.2k
Forks
1.5k
Avg merge
4h 57m
Merged PRs (30d)
14

Description

#### Support plan

* *is this issue currently blocking your project?* (yes/no): no
* *is this issue affecting a production system?* (yes/no): no

#### Context

* *node version*: 18.13.0
* *module version*: 17.3.0
* *environment* (e.g. node, browser, native): node
* *used with* (e.g. hapi application, another framework, standalone, ...): joiful/standalone
* *any other relevant information*: tsconfig.json set with "exactOptionalPropertyTypes": true

#### What problem are you trying to solve?

We are using a stricter typescript config with exactOptionalPropertyTypes set as true, and we get TS errors when defining what an array of items can be.

```js
import Joi from 'joi';
import { array } from 'joiful';

@array()
.items(
Joi.string().guid({
version: ['uuidv1', 'uuidv2', 'uuidv3', 'uuidv4', 'uuidv5'],
}),
Joi.number(),
Joi.object()
)
.required()
identifier!: (string | number | JSONObject)[];
```

Causes this typescript error:

```
error TS2379: Argument of type 'StringSchema' is not assignable to parameter of type 'Schema' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Type 'StringSchema' is not assignable to type 'StringSchema' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Types of property 'alter' are incompatible.
Type '(targets: Record) => Schema>) => StringSchema' is not assignable to type '(targets: Record) => StringSchema'.
Types of parameters 'targets' and 'targets' are incompatible.
Type 'Record' is not assignable to type 'Record) => Schema>'.
'string' index signatures are incompatible.
Type 'SchemaFunction' is not assignable to type '(schema: StringSchema) => Schema'.

200 Joi.string().guid({
~~~~~~~~~~~~~~~~~~~
201 version: ['uuidv1', 'uuidv2', 'uuidv3', 'uuidv4', 'uuidv5'],
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
202 }),
~~~~~~~~~~~~~~
```

To get around this error we have to use `any` which is not ideal, and also tell the linter to stop warning us about the use of any:

```js
@array()
.items(
Joi.string().guid({
version: ['uuidv1', 'uuidv2', 'uuidv3', 'uuidv4', 'uuidv5'],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Joi.number() as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Joi.object() as any
)
.required()
```

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

Updating the joi optional types to include `undefined` per the [TS documentation](https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes) would solve the issue and add support for that setting.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.