Skip to content

A few toJsonSchema requests #1379

@mmkal

Description

@mmkal

Request a feature

🤷 Motivation

Hi! I'm working on adding arktype support to trpc-cli. How it's currently working is to use .toJsonSchema() to in theory get it in a form that zod can also target via zod-to-json-schema.

It works (draft PR here if you're curious), but there are a few edge cases I've hit that I think could be improved in arktype:

  1. Automatically use the "in" type. In this case, and likely in most(?), what's actually wanted is a json-schema for data that will be successfully parsed by the type. Example - type('number').pipe(n => `${n}th`). It's possible to just do myType.in.toJsonSchema() but I think it'd be helpful for arktype to do this automatically (and make the throw-y behaviour opt in instead)
  2. Same deal for .narrow. That produces an error like Predicate $ark.fn13 is not convertible to JSON Schema, and it's even harder to get around - you can use myType.basis.toJsonSchema() but basis doesn't seem to be an exposed property.
  3. Strange .default(...) behaviour. With zod+zod-to-json-schema, I can do z.string().default('hi') and get {type: 'string', default: 'hi'}. With arktype as far as I can tell there isn't an equivalent. type('string').default('hi') does something quite different (returns a tuple) - and type({foo: 'string = "hi"'}) doesn't put a default property on the resultant schema.
  4. This one might be considered too hacky to want to support - but zod-to-json-schema maps undefined to {"not": {}}. My use case is that I want to allow optional positional arguments in a CLI by saying that the input is type('string | undefined'). Maybe rather than enabling by default, there could be some way of configuring .toJsonSchema to map undefined to a user-defined json schema somehow?

Some of these combine to make things even harder - sometimes needing .in and sometimes needing the secret .basis makes it complex for consumers to write a reliable algorithm for function getTypeThatWillActuallyBeConvertibleToJsonSchema(input: type.Any) {...} - but this algorithm could sensibly live in arktype. Especially when they're nested insed a union or something.

💡 Solution

1 & 2 - I think there could be an algorithm to get the "basis" type which should be used for the json schema (maybe something like this exists already?)
3 - might be simple - although it seems from the docs that default is only intended for object/tuple elements, which is a shame because morphs don't allow easily for static usage like this, but not a huge problem
4 - not sure exactly, I guess this is related to how primitives can't be optional/defaultable

An alternative would be traversing the arktype types as they are, rather than relying on json-schema conversion, but I would rather not do that, since json-schema seems like a sensible common language for trpc-cli to be able to support, and I don't want to need to keep up to speed on arktype's innards to have things work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Done (merged or closed)

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions