Can the output of `.json` be used to construct an arktype schema?

For example:
const booleanJson = type.boolean.json
console.log(booleanJson)
// => [ { unit: false }, { unit: true } ]

// what I'm after is an API that let's me do this:

type([ { unit: false }, { unit: true }])

// or more directly:
type(type.boolean.json)
const booleanJson = type.boolean.json
console.log(booleanJson)
// => [ { unit: false }, { unit: true } ]

// what I'm after is an API that let's me do this:

type([ { unit: false }, { unit: true }])

// or more directly:
type(type.boolean.json)
22 Replies
ssalbdivad
ssalbdivad2d ago
type.schema(type.boolean.json) although it will fail for non-serializable constraints You also probably have to cast the input for now type.schema(type.boolean.json as never) or something since it's not officially supported because of the serializability issue
ssalbdivad
ssalbdivad2d ago
GitHub
How to construct a new Type from an exiting Type's internal JSON re...
Related to #1225 & #818 Type.toJSON()/.json return an internal representation of that type, parsed and reorganized from what is passed to `type(): const device = type({ platform: "'and...
ahrjarrett
ahrjarrettOP2d ago
awesome -- thank you!
ahrjarrett
ahrjarrettOP2d ago
i've got a possible bug -- going to open an issue for it, but wanted to double check here to make sure it isn't just user error on my part https://stackblitz.com/edit/vitest-dev-vitest-ddhwwn9j?file=test%2Frepro.test.ts
andrew jarrett
StackBlitz
arktype union possible bug repro - StackBlitz
Run official live example code for Vitest Basic, created by Vitest Dev on StackBlitz
ahrjarrett
ahrjarrettOP2d ago
tl;dr
const schema1 = type.Record(
"string",
type("3 <= null[] <= 10").or('false').or([type.undefined])
)

const schema2 = type.Record(
"string",
type('null[]').or('false').or([type.undefined])
)

schema1({ a: false }) // => { a: false }
schema2({ a: false }) // => ArkErrors[]
const schema1 = type.Record(
"string",
type("3 <= null[] <= 10").or('false').or([type.undefined])
)

const schema2 = type.Record(
"string",
type('null[]').or('false').or([type.undefined])
)

schema1({ a: false }) // => { a: false }
schema2({ a: false }) // => ArkErrors[]
not sure why the range constraint would change the behavior there. also not sure why, but the [type.undefined] is necessary too this doesn't come from an actual use case, this was a generated schema
ssalbdivad
ssalbdivad2d ago
Yeah that does look like a bug
ahrjarrett
ahrjarrettOP2d ago
cool. i'll raise the issue. unless you'd prefer i put it on reddit?? hah 😭 that shit
ssalbdivad
ssalbdivad2d ago
It probably has something to do with discrimination
ahrjarrett
ahrjarrettOP2d ago
cool. thanks for everything you do!
ssalbdivad
ssalbdivad2d ago
I will probably see if I can fix this now, hopefully relatively simple 🙏
ahrjarrett
ahrjarrettOP2d ago
oh wow, i haven't seen the playground until now. nice!
ssalbdivad
ssalbdivad2d ago
Ahh interesting, I see the issue
{
kind: 'unit',
path: [ '0' ],
cases: {
undefined: [
{
sequence: {...},
proto: 'Array',
exactLength: 1
},
{
sequence: {...},
proto: 'Array'
}
],
null: { sequence: { unit: null }, proto: 'Array' },
default: { unit: false }
}
}
{
kind: 'unit',
path: [ '0' ],
cases: {
undefined: [
{
sequence: {...},
proto: 'Array',
exactLength: 1
},
{
sequence: {...},
proto: 'Array'
}
],
null: { sequence: { unit: null }, proto: 'Array' },
default: { unit: false }
}
}
This is the discriminant The problem is that in this case, default is equivalent to undefined, so the default case is never hit
ahrjarrett
ahrjarrettOP2d ago
https://github.com/arktypeio/arktype/issues/1440 default means default discriminant? not like, default value?
ssalbdivad
ssalbdivad2d ago
This whole thing represents the way the discrimination works i.e. check the value at path [0], then depending on which case it ===, apply the remaining checks But the combination of the array + tuple leads to a bad result here
ahrjarrett
ahrjarrettOP2d ago
gotcha. yeah it'd be a pretty strange schema to write by hand
ssalbdivad
ssalbdivad2d ago
Definitely a good case to fix though! Glad you caught it Oh the ...s make the example a bit more confusing
ssalbdivad
ssalbdivad2d ago
This is the full case. I'm glad it gets the possibility of null[] having the value undefined
No description
ssalbdivad
ssalbdivad2d ago
So the only problem is that default also needs to be grouped with undefined here
ahrjarrett
ahrjarrettOP2d ago
tbh, i'm not sure i understand hah. specifically i think the { undefined: [{ sequence: { prefix: [{ unit: 'undefined' }] } }] } bit is confusing me
ssalbdivad
ssalbdivad2d ago
It's saying if the value at 0 is undefined, , check that the root value is either [undefined] or a null[] (int his case it would have to be []) But actually this discriminant is degenerate because once you include false you haven't discriminated anything
ssalbdivad
ssalbdivad2d ago
In the other case, it falls back to a better discriminant at the root of the type
No description
ahrjarrett
ahrjarrettOP2d ago
oh okay, that makes more sense. cool i've got a workaround here locally, but i'll follow that issue so i know when i can rip it out

Did you find this page helpful?