diff --git a/package-lock.json b/package-lock.json index 24a7963cb..2a2ee6347 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox", - "version": "0.31.12", + "version": "0.31.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", - "version": "0.31.12", + "version": "0.31.13", "license": "MIT", "devDependencies": { "@sinclair/hammer": "^0.17.1", diff --git a/package.json b/package.json index db2656753..fbb0e3392 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sinclair/typebox", - "version": "0.31.12", + "version": "0.31.13", "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", diff --git a/src/value/convert.ts b/src/value/convert.ts index fd64cfacf..60ba2e1f3 100644 --- a/src/value/convert.ts +++ b/src/value/convert.ts @@ -173,6 +173,12 @@ function TDate(schema: Types.TDate, references: Types.TSchema[], value: any): un function TInteger(schema: Types.TInteger, references: Types.TSchema[], value: any): unknown { return TryConvertInteger(value) } +function TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: any): unknown { + // prettier-ignore + return (schema.allOf.every(schema => Types.TypeGuard.TObject(schema))) + ? Visit(Types.Type.Composite(schema.allOf as Types.TObject[]), references, value) + : Visit(schema.allOf[0], references, value) +} function TLiteral(schema: Types.TLiteral, references: Types.TSchema[], value: any): unknown { return TryConvertLiteral(schema, value) } @@ -247,6 +253,8 @@ function Visit(schema: Types.TSchema, references: Types.TSchema[], value: any): return TDate(schema_, references_, value) case 'Integer': return TInteger(schema_, references_, value) + case 'Intersect': + return TIntersect(schema_, references_, value) case 'Literal': return TLiteral(schema_, references_, value) case 'Null': @@ -278,7 +286,6 @@ function Visit(schema: Types.TSchema, references: Types.TSchema[], value: any): case 'AsyncIterator': case 'Constructor': case 'Function': - case 'Intersect': case 'Iterator': case 'Never': case 'Promise': diff --git a/test/runtime/value/convert/index.ts b/test/runtime/value/convert/index.ts index 09f006f09..ec3e1b6e8 100644 --- a/test/runtime/value/convert/index.ts +++ b/test/runtime/value/convert/index.ts @@ -10,6 +10,7 @@ import './date' import './enum' import './function' import './integer' +import './intersect' import './iterator' import './keyof' import './literal' diff --git a/test/runtime/value/convert/intersect.ts b/test/runtime/value/convert/intersect.ts new file mode 100644 index 000000000..5c2e2bb37 --- /dev/null +++ b/test/runtime/value/convert/intersect.ts @@ -0,0 +1,45 @@ +import { Value } from '@sinclair/typebox/value' +import { Type } from '@sinclair/typebox' +import { Assert } from '../../assert/index' + +describe('value/convert/Intersect', () => { + it('Should convert intersected objects', () => { + // prettier-ignore + const T = Type.Intersect([ + Type.Object({ x: Type.Number() }), + Type.Object({ y: Type.Number() }) + ]) + const R = Value.Convert(T, { x: '1', y: '2' }) + Assert.IsEqual(R, { x: 1, y: 2 }) + }) + it('Should not convert for non object exclusive intersect', () => { + // prettier-ignore + const T = Type.Intersect([ + Type.Number(), + Type.Object({ x: Type.Number() }), + Type.Object({ y: Type.Number() }) + ]) + const R = Value.Convert(T, { x: '1', y: '2' }) + Assert.IsEqual(R, { x: '1', y: '2' }) + }) + it('Should convert first type for object exclusive intersect 1', () => { + // prettier-ignore + const T = Type.Intersect([ + Type.Number(), + Type.Object({ x: Type.Number() }), + Type.Object({ y: Type.Number() }) + ]) + const R = Value.Convert(T, '123') + Assert.IsEqual(R, 123) + }) + it('Should convert first type for object exclusive intersect 2', () => { + // prettier-ignore + const T = Type.Intersect([ + Type.Object({ x: Type.Number() }), + Type.Object({ y: Type.Number() }), + Type.Number(), + ]) + const R = Value.Convert(T, { x: '3', y: '4' }) + Assert.IsEqual(R, { x: 3, y: '4' }) + }) +})