Skip to content

Commit c8bee29

Browse files
committed
fix: proper types for more complex cases of array
Fixes #3086
1 parent 0ffadef commit c8bee29

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

lib/index.d.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,19 @@ declare namespace Joi {
17051705

17061706
type ComparatorFunction = (a: any, b: any) => boolean;
17071707

1708+
type UnwrapSchemaLikeWithoutArray<T> = T extends SchemaLikeWithoutArray<
1709+
infer U
1710+
>
1711+
? U
1712+
: never;
1713+
1714+
type NoNestedArrays<T extends readonly unknown[]> = Extract<
1715+
T[number],
1716+
readonly unknown[]
1717+
> extends never
1718+
? T
1719+
: never;
1720+
17081721
interface ArraySchema<TSchema = any[]> extends AnySchema<TSchema> {
17091722
/**
17101723
* Verifies that an assertion passes for at least one item in the array, where:
@@ -1754,7 +1767,16 @@ declare namespace Joi {
17541767
e: SchemaLikeWithoutArray<E>,
17551768
f: SchemaLikeWithoutArray<F>
17561769
): ArraySchema<(A | B | C | D | E | F)[]>;
1757-
items<TItems>(...types: SchemaLikeWithoutArray<TItems>[]): this;
1770+
items<
1771+
TItems,
1772+
TTItems extends SchemaLikeWithoutArray<TItems>[] = SchemaLikeWithoutArray<TItems>[]
1773+
>(
1774+
...types: NoNestedArrays<TTItems>
1775+
): ArraySchema<
1776+
{
1777+
[I in keyof TTItems]: UnwrapSchemaLikeWithoutArray<TTItems[I]>;
1778+
}[number][]
1779+
>;
17581780

17591781
/**
17601782
* Specifies the exact number of items in the array.

test/index.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,32 @@ expect.error(arrSchema.items([schemaMap, schemaMap, schemaLike]));
401401
let value1 = Joi.array().items(Joi.string(), Joi.boolean(), Joi.number(), Joi.object({key: Joi.string()}));
402402
expect.type<Joi.ArraySchema<(string | number | boolean | {key: string})[]>>(value1)
403403

404-
expect.type<Joi.ArraySchema<boolean[]>>(Joi.array().items(Joi.boolean()));
405-
expect.type<Joi.ArraySchema<number[][]>>(Joi.array().items(Joi.array().items(Joi.number())));
404+
const arr1 = Joi.array().items(Joi.boolean());
405+
expect.type<Joi.ArraySchema<boolean[]>>(arr1);
406+
const arr2 = Joi.array().items<boolean>(Joi.boolean());
407+
expect.type<Joi.ArraySchema<boolean[]>>(arr2);
408+
const arr3 = Joi.array().items<number>(Joi.number());
409+
expect.type<Joi.ArraySchema<number[]>>(arr3);
410+
const arr4 = Joi.array().items(Joi.array().items(Joi.number()));
411+
expect.type<Joi.ArraySchema<number[][]>>(arr4);
412+
const arr5 = Joi.array().items(Joi.number(), Joi.string());
413+
expect.type<Joi.ArraySchema<(number | string)[]>>(arr5);
414+
const arr6 = Joi.array().items(Joi.number(), Joi.string(), Joi.boolean());
415+
expect.type<Joi.ArraySchema<(number | string | boolean)[]>>(arr6);
416+
const arr7 = Joi.array().items(process.env.NODE_ENV ? Joi.string() : Joi.number());
417+
expect.type<Joi.ArraySchema<(string | number)[]>>(arr7);
418+
const arr8 = Joi.array().items(process.env.NODE_ENV ? Joi.string() : Joi.number(), process.env.NODE_ENV ? Joi.boolean() : Joi.date());
419+
expect.type<Joi.ArraySchema<(string | number | boolean | Date)[]>>(arr8);
420+
const arr9 = Joi.array().items(
421+
Joi.binary(),
422+
Joi.boolean(),
423+
Joi.date(),
424+
Joi.function(),
425+
Joi.number(),
426+
Joi.object<Record<string,string>>(),
427+
Joi.string(),
428+
);
429+
expect.type<Joi.ArraySchema<(Buffer | boolean | Date | Function | number | Record<string, string> | string)[]>>(arr9);
406430

407431
// - - - - - - - -
408432

0 commit comments

Comments
 (0)