Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standard Schema support #1291

Open
notramo opened this issue Dec 19, 2024 · 1 comment
Open

Standard Schema support #1291

notramo opened this issue Dec 19, 2024 · 1 comment

Comments

@notramo
Copy link

notramo commented Dec 19, 2024

@ianstormtaylor are there any plans on supporting the Standard Schema interface in Superstruct?

https://github.com/standard-schema/standard-schema/

@Loxoz
Copy link

Loxoz commented Feb 8, 2025

I may be wrong, but I don't think Standard Schema should be implemented directly in Superstruct.
One of the reasons I use Superstruct is that it is light and tree-shaking when bundled, and this might add some weight to it.

However, even if a little bit against Standard Schema's philosophy, it is very easy to make an adapter to any Struct, validate it with Standard Schema's function, and still get correct types.

Here is a simple implementation:

import { Struct, Infer } from "superstruct";
import * as s from "superstruct";
import { StandardSchemaV1 } from "@standard-schema/spec";

export type StructSchema<S extends Struct<any>> = StandardSchemaV1<unknown, Infer<S>>;

export function structSchema<S extends Struct<any>>(struct: S): StructSchema<S> {
    return {
        "~standard": {
            version: 1,
            vendor: "superstruct",
            validate(input) {
                const [err, value] = struct.validate(input, { coerce: true });

                if (err) {
                    return { issues: [{ message: err.message, path: err.path.map(String) }] };
                }

                return { value };
            },
        },
    };
}

example usage:

const schema = structSchema(s.type({ foo: s.literal("bar") }));

const result1 = await schema["~standard"].validate({ foo: "bar" });
console.log(result1);
/*
{ value: { foo: 'bar' } }
*/

const result2 = await schema["~standard"].validate({ notFoo: "notBar" });
console.log(result2);
/*
{
  "issues": [
    {
      "message": "At path: foo -- Expected the literal `\"bar\"`, but received: undefined",
      "path": [
        "foo"
      ]
    }
  ]
}
*/

if (result2.issues) { // will throw
    throw new Error(JSON.stringify(result2.issues, null, 2));
}

result2.value; // correctly typed
const simpleSchema = structSchema(s.boolean());

console.log(await simpleSchema["~standard"].validate(true));
/*
{ value: true }
*/
console.log(await simpleSchema["~standard"].validate(undefined));
/*
{
  issues: [
    {
      message: 'Expected a value of type `boolean`, but received: `undefined`',
      path: []
    }
  ]
}
*/

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants