diff --git a/changelog/0.33.0.md b/changelog/0.33.0.md index 9911727..b098d7e 100644 --- a/changelog/0.33.0.md +++ b/changelog/0.33.0.md @@ -1,5 +1,6 @@ ### 0.33.0 - +- [Revision 0.33.9](https://github.com/sinclairzx81/typebox/pull/984) + - [887](https://github.com/sinclairzx81/typebox/issues/887) Generate Nested Intersect Errors - [Revision 0.33.8](https://github.com/sinclairzx81/typebox/pull/983) - [982](https://github.com/sinclairzx81/typebox/issues/982) Prevent Intersect Transform Encode callback from being called twice - [974](https://github.com/sinclairzx81/typebox/issues/974) Make strict the Encode and Decode return type diff --git a/package-lock.json b/package-lock.json index 2bdb89d..9acbb82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox", - "version": "0.33.8", + "version": "0.33.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", - "version": "0.33.8", + "version": "0.33.9", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.13.2", diff --git a/package.json b/package.json index 2d0f7a3..cdc4759 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sinclair/typebox", - "version": "0.33.8", + "version": "0.33.9", "description": "Json Schema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", diff --git a/src/errors/errors.ts b/src/errors/errors.ts index f81de1a..edb58a0 100644 --- a/src/errors/errors.ts +++ b/src/errors/errors.ts @@ -312,13 +312,16 @@ function* FromInteger(schema: TInteger, references: TSchema[], path: string, val } } function* FromIntersect(schema: TIntersect, references: TSchema[], path: string, value: any): IterableIterator { + let hasError = false for (const inner of schema.allOf) { - const next = Visit(inner, references, path, value).next() - if (!next.done) { - yield Create(ValueErrorType.Intersect, schema, path, value) - yield next.value + for (const error of Visit(inner, references, path, value)) { + hasError = true + yield error } } + if (hasError) { + return yield Create(ValueErrorType.Intersect, schema, path, value) + } if (schema.unevaluatedProperties === false) { const keyCheck = new RegExp(KeyOfPattern(schema)) for (const valueKey of Object.getOwnPropertyNames(value)) { diff --git a/test/runtime/errors/types/intersect.ts b/test/runtime/errors/types/intersect.ts index e45b0dd..5e1f8f1 100644 --- a/test/runtime/errors/types/intersect.ts +++ b/test/runtime/errors/types/intersect.ts @@ -4,21 +4,46 @@ import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Intersect', () => { - const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) it('Should pass 0', () => { + const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Resolve(T, { x: 1, y: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { + const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Resolve(T, { x: 1 }) - Assert.IsEqual(R.length, 2) - Assert.IsEqual(R[0].type, ValueErrorType.Intersect) - Assert.IsEqual(R[1].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R.length, 3) + Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R[1].type, ValueErrorType.Number) + Assert.IsEqual(R[2].type, ValueErrorType.Intersect) }) it('Should pass 2', () => { + const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Resolve(T, { y: 1 }) - Assert.IsEqual(R.length, 2) - Assert.IsEqual(R[0].type, ValueErrorType.Intersect) - Assert.IsEqual(R[1].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R.length, 3) + Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R[1].type, ValueErrorType.Number) + Assert.IsEqual(R[2].type, ValueErrorType.Intersect) + }) + // ---------------------------------------------------------------- + // https://github.com/sinclairzx81/typebox/issues/887 + // ---------------------------------------------------------------- + it('Should pass 3', () => { + const A = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) + const B = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ z: Type.Number() })]) + const T = Type.Intersect([A, B]) + const R = Resolve(T, {}) + Assert.IsEqual(R.length, 11) + Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R[1].type, ValueErrorType.Number) + Assert.IsEqual(R[2].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R[3].type, ValueErrorType.Number) + Assert.IsEqual(R[4].type, ValueErrorType.Intersect) + Assert.IsEqual(R[5].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R[6].type, ValueErrorType.Number) + Assert.IsEqual(R[7].type, ValueErrorType.ObjectRequiredProperty) + Assert.IsEqual(R[8].type, ValueErrorType.Number) + Assert.IsEqual(R[9].type, ValueErrorType.Intersect) + Assert.IsEqual(R[10].type, ValueErrorType.Intersect) }) })