Skip to content

Is it possible to combine GenericSchema with variant? #842

@AndreiCravtov

Description

@AndreiCravtov

I am trying to make a schema-constructor corresponding to a Rust-style Result type, more concretely it has this type:

type Ok<T> = { success: true; data: T }
type Err<E> = { success: false; error: E }
type Result<T, E> = Ok<T> | Err<E>

I can make a schema-constructor like this:

const ResultSchema = <TSchema extends GenericSchema, ESchema extends GenericSchema>(dataSchema: TSchema, errorSchema: ESchema) => union([
    object({ success: literal(true), data: dataSchema }),
    object({ success: literal(false), error: errorSchema }),
])

And that works, but this is a discriminated union so variant would be more appropriate. However when I try to use it

const ResultSchema = <TSchema extends GenericSchema, ESchema extends GenericSchema>(dataSchema: TSchema, errorSchema: ESchema) => variant("success", [
    object({ success: literal(true), data: dataSchema }),
    object({ success: literal(false), error: errorSchema }),
])

I get these type errors

Type 'ObjectSchema<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, undefined>' is not assignable to type 'VariantOption<"success">'.
  Type 'ObjectSchema<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, undefined>' is not assignable to type 'ObjectSchema<Record<"success", BaseSchema<unknown, unknown, BaseIssue<unknown>>>, ErrorMessage<ObjectIssue> | undefined>'.
    The types returned by '_run(...)' are incompatible between these types.
      Type 'Dataset<{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }, ObjectIssue | InferObjectIssue<...>>' is not assignable to type 'Dataset<{ success: unknown; }, BaseIssue<unknown> | ObjectIssue>'.
        Type 'TypedDataset<{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }, ObjectIssue | InferObjectIssue<...>>' is not assignable to type 'Dataset<{ success: unknown; }, BaseIssue<unknown> | ObjectIssue>'.
          Type 'TypedDataset<{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }, ObjectIssue | InferObjectIssue<...>>' is not assignable to type 'TypedDataset<{ success: unknown; }, BaseIssue<unknown> | ObjectIssue>'.
            Property 'success' is missing in type '{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly data: TSchema; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }' but required in type '{ success: unknown; }'.

Not sure what any of this means, but I'm suspecting there is some small detail I missed or some generic I need to use. Now, I can just use union but I am curious why variant doesn't work.

Metadata

Metadata

Assignees

Labels

fixA smaller enhancement or bug fixworkaroundWorkaround fixes problem

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions