From fdf3e62aca4e113ddf709e58bb8ae88e3abc4f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20M=C3=BCller?= Date: Sun, 30 Jun 2024 22:31:01 +0200 Subject: [PATCH] Fix incorrectly passing validation for arrays in object(), type(), and record() (#1252) * Add isNonArrayObject util * Fix incorrectly passing validation when arrays are passed to object() * Fix incorrectly passing validation when arrays are passed to record() * Fix incorrectly passing validation when arrays are passed to type() --- src/structs/types.ts | 14 +++++++++----- src/utils.ts | 8 ++++++++ test/validation/object/invalid-array.ts | 15 +++++++++++++++ test/validation/record/invalid-array.ts | 15 +++++++++++++++ test/validation/type/invalid-array.ts | 15 +++++++++++++++ 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 test/validation/object/invalid-array.ts create mode 100644 test/validation/record/invalid-array.ts create mode 100644 test/validation/type/invalid-array.ts diff --git a/src/structs/types.ts b/src/structs/types.ts index 372aa5b1..c1cfccfa 100644 --- a/src/structs/types.ts +++ b/src/structs/types.ts @@ -6,6 +6,7 @@ import { print, run, isObject, + isNonArrayObject, AnyStruct, InferStructTuple, UnionToIntersection, @@ -316,11 +317,12 @@ export function object(schema?: S): any { }, validator(value) { return ( - isObject(value) || `Expected an object, but received: ${print(value)}` + isNonArrayObject(value) || + `Expected an object, but received: ${print(value)}` ) }, coercer(value, ctx) { - if (!isObject(value) || Array.isArray(value)) { + if (!isNonArrayObject(value)) { return value } @@ -380,7 +382,8 @@ export function record( }, validator(value) { return ( - isObject(value) || `Expected an object, but received: ${print(value)}` + isNonArrayObject(value) || + `Expected an object, but received: ${print(value)}` ) }, }) @@ -496,11 +499,12 @@ export function type( }, validator(value) { return ( - isObject(value) || `Expected an object, but received: ${print(value)}` + isNonArrayObject(value) || + `Expected an object, but received: ${print(value)}` ) }, coercer(value) { - return isObject(value) ? { ...value } : value + return isNonArrayObject(value) ? { ...value } : value }, }) } diff --git a/src/utils.ts b/src/utils.ts index aa80983e..5c05d1e1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -17,6 +17,14 @@ export function isObject(x: unknown): x is object { return typeof x === 'object' && x != null } +/** + * Check if a value is a non-array object. + */ + +export function isNonArrayObject(x: unknown): x is object { + return isObject(x) && !Array.isArray(x) +} + /** * Check if a value is a plain object. */ diff --git a/test/validation/object/invalid-array.ts b/test/validation/object/invalid-array.ts new file mode 100644 index 00000000..0555dae0 --- /dev/null +++ b/test/validation/object/invalid-array.ts @@ -0,0 +1,15 @@ +import { object } from '../../../src' + +export const Struct = object() + +export const data = [] + +export const failures = [ + { + value: [], + type: 'object', + refinement: undefined, + path: [], + branch: [data], + }, +] diff --git a/test/validation/record/invalid-array.ts b/test/validation/record/invalid-array.ts new file mode 100644 index 00000000..a1e58fc7 --- /dev/null +++ b/test/validation/record/invalid-array.ts @@ -0,0 +1,15 @@ +import { record, string, number } from '../../../src' + +export const Struct = record(string(), number()) + +export const data = [] + +export const failures = [ + { + value: [], + type: 'record', + refinement: undefined, + path: [], + branch: [data], + }, +] diff --git a/test/validation/type/invalid-array.ts b/test/validation/type/invalid-array.ts new file mode 100644 index 00000000..a0ec3972 --- /dev/null +++ b/test/validation/type/invalid-array.ts @@ -0,0 +1,15 @@ +import { type } from '../../../src' + +export const Struct = type({}) + +export const data = [] + +export const failures = [ + { + value: [], + type: 'type', + refinement: undefined, + path: [], + branch: [data], + }, +]