For the last few months, I have had to pause the development of rescript-rest because an important feature was missing in my other library, rescript-schema. I finally managed to implement it, and I am happy to announce the release of ReScript Schema V7 as well as the continuation of rescript-rest development.
ReScript Schema V7
S.object superpowers
I needed this for rescript-rest, and I hope it will be useful for many other rescript-schema users.
s.flatten
Now, it’s possible to spread/flatten an object schema in another object schema, allowing you to reuse schemas in a more powerful way.
type entityData = {
name: string,
age: int,
}
type entity = {
id: string,
...entityData,
}
let entityDataSchema = S.object(s => {
name: s.field("name", S.string),
age: s.field("age", S.int),
})
let entitySchema = S.object(s => {
let {name, age} = s.flatten(entityDataSchema)
{
id: s.field("id", S.string),
name,
age,
}
})
s.nestedField
A new nice way to parse nested fields:
let schema = S.object(s => {
{
id: s.field("id", S.string),
name: s.nestedField("data", "name", S.string)
age: s.nestedField("data", "name", S.int),
}
})
Object destructuring
Also, it’s possible to destructure object field schemas inside of the definition. You could also notice it in the s.flatten example 
let entitySchema = S.object(s => {
let {name, age} = s.field("data", entityDataSchema)
{
id: s.field("id", S.string),
name,
age,
}
})
While the example with
s.flattenexpect an object with the type{id: string, name: string, age: int}, the example above and withs.nestedFieldwill expect an object with the type{id: string, data: {name: string, age: int}}.
Extend field with another object schema
You can define object field multiple times to extend it with more fields:
let entitySchema = S.object(s => {
let {name, age} = s.field("data", entityDataSchema)
let additionalData = s.field("data", s => {
"friends": s.field("friends", S.array(S.string))
})
{
id: s.field("id", S.string),
name,
age,
friends: additionalData["friends"],
}
})
Destructuring works only with not-transformed object schemas. Be careful since it’s not protected by type system.
Autocomplete improvements
Updated context type names to s for better auto-complete in your IDE.
-
effectCtx→s -
Object.ctx→Object.s -
Tuple.ctx→Tuple.s -
schemaCtx→Schema.s -
catchCtx→Catch.s
S.json redesign
Added unsafe mode for S.json:
-
S.json→S.json(~validate: bool) - More flexible
- Improved tree-shaking
- Tools using
rescript-schemacan get the info from thetaggedtype:JSON→JSON({validated: bool})
Other cool changes and sometimes breaking
-
Added
serializeToJsonStringOrRaiseWith -
Allow to create
S.unionwith a single item -
Removed
s.failWithError. UseS.Error.raiseinstead -
PPX: Removed
@schemafor type expressions. Use@s.matchesinstead. -
Removed async support for
S.union. Please create an issue if you used the feature -
Improved parsing performance of
S.arrayandS.dict~3 times -
Automatic serializing stopped working for tuples/objects/unions of literals. Use
S.literalinstead -
Removed
InvalidTupleSizeerror code in favor ofInvalidType -
Changed payload of
ObjectandTuplevariants in thetaggedtype -
Redesigned
Literalmodule to make it more efficient- The
S.Literal.ttype was renamed toS.literal, became private and changed structure. UseS.Literal.parseto create instances of the type -
S.Literal.classify→S.Literal.parse -
S.Literal.toText→S.Literal.toString. Also, started using.toStringforFunctionliterals and removed spaces forDictandArrayliterals to make them look the same as theJSON.stringifyoutput
- The
-
Moved built-in refinements from nested modules to improve tree-shaking:
-
S.Int.min→S.intMin -
S.Int.max→S.intMax -
S.Int.port→S.port -
S.Float.min→S.floatMin -
S.Float.max→S.floatMax -
S.Array.min→S.arrayMinLength -
S.Array.max→S.arrayMaxLength -
S.Array.length→S.arrayLength -
S.String.min→S.stringMinLength -
S.String.max→S.stringMaxLength -
S.String.length→S.stringLength -
S.String.email→S.email -
S.String.uuid→S.uuid -
S.String.cuid→S.cuid -
S.String.url→S.url -
S.String.pattern→S.pattern -
S.String.datetime→S.datetime -
S.String.trim→S.trim -
S.Int.min→S.intMin -
S.Int.max→S.intMax -
S.Number.max→S.numberMax/S.integerMax -
S.Number.min→S.numberMin/S.integerMin
-
While the example with