diff --git a/package-lock.json b/package-lock.json index 057029d..53a82d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox-adapter", - "version": "0.8.1", + "version": "0.8.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox-adapter", - "version": "0.8.1", + "version": "0.8.2", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.17.2", diff --git a/package.json b/package.json index 9bc121b..9eff098 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sinclair/typebox-adapter", - "version": "0.8.1", + "version": "0.8.2", "description": "Integrate Valibot and Zod with TypeBox", "author": "sinclairzx81", "license": "MIT", diff --git a/src/zod.ts b/src/zod.ts index 8ad36b0..e44816c 100644 --- a/src/zod.ts +++ b/src/zod.ts @@ -108,6 +108,19 @@ function FromDefault(def: Def): tb.TSchema { return tb.CloneType(FromType(def.innerType), { default: def.defaultValue() }) } // ------------------------------------------------------------------ +// DiscriminatedUnion +// ------------------------------------------------------------------ +// prettier-ignore +type TFromDiscriminatedUnion[], Result extends tb.TSchema[] = []> = ( + Types extends [infer Left extends z.ZodObject, ...infer Right extends z.ZodObject[]] + ? TFromDiscriminatedUnion]> + : tb.TUnion +) +function FromDiscriminatedUnion[]>>(def: Def): tb.TSchema { + const types = def.options.map((type) => FromType(type)) + return tb.Union(types, { discriminator: def.discriminator }) +} +// ------------------------------------------------------------------ // Effects // ------------------------------------------------------------------ type TFromEffects = tb.Ensure, Output>> @@ -322,6 +335,7 @@ type TFromType = ( Type extends z.ZodBoolean ? TFromBoolean : Type extends z.ZodDate ? TFromDate : Type extends z.ZodDefault ? TFromDefault : + Type extends z.ZodDiscriminatedUnion ? TFromDiscriminatedUnion : Type extends z.ZodEffects ? TFromEffects : Type extends z.ZodLiteral ? TFromLiteral : Type extends z.ZodNullable ? TFromNullable : @@ -353,6 +367,7 @@ function FromType(type: Type): tb.TSchema { type instanceof z.ZodBoolean ? FromBoolean(type._def) : type instanceof z.ZodDate ? FromDate(type._def) : type instanceof z.ZodDefault ? FromDefault(type._def) : + type instanceof z.ZodDiscriminatedUnion ? FromDiscriminatedUnion(type._def) : type instanceof z.ZodEffects ? FromEffects(type) : type instanceof z.ZodLiteral ? FromLiteral(type._def) : type instanceof z.ZodNullable ? FromNullable(type._def) : diff --git a/test/zod.ts b/test/zod.ts index 78607bd..e00ec2b 100644 --- a/test/zod.ts +++ b/test/zod.ts @@ -46,6 +46,20 @@ describe('Zod', () => { Assert.IsTrue(TypeGuard.IsDate(T)) }) // ---------------------------------------------------------------- + // DiscriminatedUnion + // ---------------------------------------------------------------- + it('Should map DiscriminatedUnion', () => { + const A = z.object({ type: z.literal('A') }) + const B = z.object({ type: z.literal('B') }) + const C = z.object({ type: z.literal('C') }) + const T = Box(z.discriminatedUnion('type', [A, B, C])) + Assert.IsTrue(TypeGuard.IsUnion(T)) + Assert.IsEqual(T.discriminator, 'type') + Assert.IsTrue(T.anyOf[0].properties.type.const === 'A') + Assert.IsTrue(T.anyOf[1].properties.type.const === 'B') + Assert.IsTrue(T.anyOf[2].properties.type.const === 'C') + }) + // ---------------------------------------------------------------- // Effects // ---------------------------------------------------------------- it('Should map Effects (Transform)', () => {