effect icon indicating copy to clipboard operation
effect copied to clipboard

Runtime error when extending `Schema.lazy` schemas

Open NexZhu opened this issue 2 years ago • 3 comments

🐛 Bug report

Is it possible to support extending extending Schema.lazy schemas (like Zod):

Currently there's runtime error when extending Schema.lazy schemas, for example:

// @ts-expect-error
const sA = Schema.lazy(() =>
  Schema.struct({
    b: sB,
  })
)

// @ts-expect-error
const sB = Schema.lazy(() =>
  Schema.struct({
    a: sA,
  })
)

const sError = pipe(
  Schema.struct({}),
  Schema.extend(sA),
)

Schema.parse(sError)({})

Error log:

Error: `extend` can only handle type literals or unions of type literals
    at map (file://.../node_modules/.pnpm/@[email protected]/node_modules/@effect/src/Schema.ts:853:15)
    at Array.map (<anonymous>)
    at flatMap (file://.../node_modules/.pnpm/@[email protected]/node_modules/@effect/src/Schema.ts:788:17)
    at Array.flatMap (<anonymous>)
    at intersectUnionMembers (file://.../node_modules/.pnpm/@[email protected]/node_modules/@effect/src/Schema.ts:787:8)
    at body (file://.../node_modules/.pnpm/@[email protected]/node_modules/@effect/src/Schema.ts:870:7)
    at ab (file://.../node_modules/.pnpm/@[email protected]/node_modules/@effect/src/Function.ts:89:28)
    at Module.pipe (file://.../node_modules/.pnpm/@[email protected]/node_modules/@effect/src/Function.ts:728:14)
    at file://.../web/backend/_src/chain/trpc.ts:33:16
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
 ELIFECYCLE  Command failed with exit code 1.

Your environment

Which versions of @effect/schema are affected by this issue? Did this work in previous versions of @effect/schema?

Software Version(s)
@effect/schema 0.19.0
TypeScript 5.1.0

NexZhu avatar May 15 '23 09:05 NexZhu

I'm not sure is possible, I have to dig into this.

Is it possible to support extending Schema.lazy schemas (like Zod):

Are you sure? Could you please provide a Zod example?

gcanti avatar May 15 '23 12:05 gcanti

@gcanti image

zwj-cheer avatar May 16 '23 01:05 zwj-cheer

@zwj-cheer using @ts-expect-error is like to define zA as any, here's the same example with the required typings:

import { z } from 'zod' // 3.21.4

interface SA {
  b: SB
}

interface SB {
  a: SA
}

const zA: z.ZodType<SA> = z.lazy(() =>
  z.object({
    b: zB
  })
)

const zB: z.ZodType<SB> = z.lazy(() =>
  z.object({
    a: zA
  })
)

const _result = z.object({}).extend(zA) // <- typescript error: 
/*
Argument of type 'ZodType<SA, ZodTypeDef, SA>' is not assignable to parameter of type 'ZodRawShape'.
  Index signature for type 'string' is missing in type 'ZodType<SA, ZodTypeDef, SA>'.ts(2345)
*/

gcanti avatar May 16 '23 06:05 gcanti