Superstruct v0.8.0 Release Notes

Release Date: 2019-10-08 // over 2 years ago
  • BREAKING

    Several structs have been renamed! Superstruct tries to mimic established naming schemes whenever possible for its API, and TypeScript is one of our main comparisons. To make things easier for people, we've renamed a few structs to more closely match their TypeScript counterparts:

    • The list struct is now called array.
    • The partial struct is now called pick.
    • The dict struct is now called record.

    Hopefully this will make them easier to understand at a glance!

    🚚 The enums struct has been removed! This was special-cased in the API previously, but you can get the exact same behavior by creating an using the array and enum structs:

    struct.array(struct.enum(['red', 'blue', 'green']))
    

    🚚 The any struct has been removed! (Not the scalar though.) Previously struct.any() was exposed that did the same thing as struct(), allowing you to use shorthands for common structs. But this was confusingly named because it has nothing to do with the 'any' scalar type. And since it was redundant it has been removed.

    The interface struct now returns the original, unaltered value! In an effort to make things more familiar, the interface struct now always returns the object that it is called with when it passes validation. So if the object was a function, a function will be returned. This makes it match more closely with the idea of "structural typing" that TypeScript and other typing systems are based on. _If you want the old behavior, use the pick struct.

    Computed values function signatures have changed! Previously a computed value would be called with a signature of (value, root) in some cases and (value, parent) in others. This was confusing, and the cause for the inconsistency was complex. This logic has been simplified, and now computed values are called with (value, branch, path) in all cases.

    struct.dynamic((value, branch, path) => {
      value === branch[branch.length - 1] // you can get the value...
      const parent = branch[branch.length - 2] // ...and the parent...
      const key = path[path.length - 1] // ...and the key...
      value === parent[key]
      const root = branch[0] // ...and the root!
    })
    

    The path is an array of keys representing the nested value's location in the root value. And the branch is an array of all of the sub values along the path to get to the current one. This allows you to always be able to receive both the parent and the root values from any location—as well as any value in between.

    The error.errors property has been renamed error.failures, and isn't cyclical. It being cyclical caused lots of issues whenever an StructError object was attempted to be serialized. And the errors property was slightly confusing because the elements of the array weren't full error objects. The new structure is easier to understand and work with.

    The error.reason property is no longer special-cased. Previously you could return a "reason" string from validator functions and it would be added to error objects. However, now you must return an error properties object (with a reason property if you'd like), and all of the properties will be added to the error object. This makes Superstruct even more flexible as far as custom error details go.

    The type property of structs have been rewritten to be more clear. This is an implementation mostly, but the struct.type string which shows up in error messages have been tweaked to be slightly more clear exactly what type they are checking for.

    NEW

    Superstruct is now written in TypeScript. It was rewritten from the ground up to make use of types, and to have better inline documented if you use a TypeScript-compatible IDE. There are probably improvements that can be made, so if you'd like to contribute please do!

    A new partial struct mimics TypeScript's Partial utility. The new struct validates that its input partially matches an object defined as a set of properties with associated types. All of the properties of the object are optional.

    A new size struct allows validating array and string lengths. The new struct validates that its input has a certain size, by checking its length property. This works strings or arrays.

    You can now provide a custom Error setting. By passing in your own constructor when configuring Superstruct you can have complete control over the exact errors that are generated by structs that fail validation.