fabian-hiller / valibot

The modular and type safe schema library for validating structural data 🤖
https://valibot.dev
MIT License
6k stars 186 forks source link

`ObjectSchema` does not satisfy predefined type (v.0.31) #641

Closed tkoyasak closed 3 months ago

tkoyasak commented 3 months ago

Hello Fabian,

I have a question about ObjectSchema. To ensure that the validated results using Valibot's object schema meet the predefined type, I defined generics ValibotSchema as follows. It was working fine in v0.30, but after updating to v0.31 (changing BaseSchema to GenericSchema), an error occurred stating that Schema does not meet ValibotSchema<Model>.

It is also related to issue #619, but do you have any solutions or plans to update?

// valibot@0.30
import * as v from 'valibot'

type ValibotSchema<T extends Record<string, unknown>> = v.ObjectSchema<
  { [K in keyof T]: v.BaseSchema<unknown, T[K]> }
>

{
  type Model = {
    id: number
  }

  const Schema = v.object({
    id: v.number(),
  }) satisfies ValibotSchema<Model>

  const result = v.parse(Schema, { id: 1 })
}

{
  type Model = {
    url: string
  }

  const Schema = v.object({
    url: v.string([v.url()]),
  }) satisfies ValibotSchema<Model>

  const result = v.parse(Schema, { url: 'https://example.com' })
}
// valibot@0.31
import * as v from 'valibot'

type ValibotSchema<T extends Record<string, unknown>> = v.ObjectSchema<
  { [K in keyof T]: v.GenericSchema<unknown, T[K]> },
  v.ErrorMessage<v.ObjectIssue> | undefined
>

{
  type Model = {
    id: number
  }

  const Schema = v.object({
    id: v.number(),
  }) satisfies ValibotSchema<Model>
//   ^ error
// Type 'ObjectSchema<{ readonly id: NumberSchema<undefined>; }, undefined>' does not satisfy the expected type 'ValibotSchema<Model>'.
// Property 'message' is missing in type 'GenericSchema<unknown, number, BaseIssue<unknown>>' but required in type 'NumberSchema<undefined>'.ts(1360)

  const result = v.parse(Schema, { id: 1 })
}

{
  type Model = {
    url: string
  }

  const Schema = v.object({
    url: v.pipe(v.string(), v.url()),
  }) satisfies ValibotSchema<Model>
//   ^ error
// Type 'ObjectSchema<{ readonly url: SchemaWithPipe<[StringSchema<undefined>, UrlAction<string, undefined>]>; }, undefined>' does not satisfy the expected type 'ValibotSchema<Model>'.
// Type 'GenericSchema<unknown, string, BaseIssue<unknown>>' is not assignable to type 'SchemaWithPipe<[StringSchema<undefined>, UrlAction<string, undefined>]>'.
// Property 'message' is missing in type 'GenericSchema<unknown, string, BaseIssue<unknown>>' but required in type 'Omit<StringSchema<undefined>, "_types" | "_run">'.ts(1360)

  const result = v.parse(Schema, { url: 'https://example.com' })
}
fabian-hiller commented 3 months ago

To be honest, I do not know why TS complains for v0.31 but not for v0.30. There is a simple workaround with slightly less type safety:

import * as v from 'valibot';

type Model = {
  id: number;
};

const Schema = v.object({
  id: v.number(),
}) satisfies v.GenericSchema<Model>;
tkoyasak commented 3 months ago

It works well. Thank you for your response!