# Migrate from Superstruct

> This document is the Markdown version of [valibot.dev/guides/migrate-from-superstruct/](https://valibot.dev/guides/migrate-from-superstruct/). For the complete documentation index, see [llms.txt](https://valibot.dev/llms.txt).

Migrating from [Superstruct](https://github.com/ianstormtaylor/superstruct) to Valibot is particularly easy since both libraries share the same functional and composable design. Most structs map directly to a Valibot schema. The following guide will help you migrate step by step and also point out important differences.

## Replace imports

The first thing to do after [installing](/guides/installation.md) Valibot is to update your imports. We recommend importing Valibot with a wildcard, which gives you access to the entire API through a single variable while remaining fully tree-shakable.

```ts
// Change this
import { object, string, assert } from 'superstruct';
const Schema = object({ key: string() });

// To this
import * as v from 'valibot';
const Schema = v.strictObject({ key: v.string() });
```

There is one detail to watch out for. Superstruct's methods expect the value as the first argument and the struct as the second. In Valibot, the schema always comes first.

```ts
// Change this
assert(input, Schema);

// To this
v.assert(Schema, input);
```

## Restructure code

Superstruct wraps structs with refinement functions like `size` and `pattern`. In Valibot you use [pipelines](/guides/pipelines.md) to do the same thing. This is a function that starts with a schema and is followed by up to 19 validation or transformation actions.

```ts
// Change this
const Schema = size(pattern(string(), /^[a-z]+$/), 3, 30);

// To this
const Schema = v.pipe(
  v.string(),
  v.regex(/^[a-z]+$/),
  v.minLength(3),
  v.maxLength(30)
);
```

The validation methods map almost one-to-one. `assert` keeps its name, `is` keeps its name with flipped arguments, `validate` returns a result object with [`safeParse`](/api/safeParse.md), and `create` becomes [`parse`](/api/parse.md).

```ts
// Change this
const [error, value] = validate(input, Schema);

// To this
const result = v.safeParse(Schema, input);
if (result.success) {
  console.log(result.output);
} else {
  console.log(result.issues);
}
```

We recommend that you read our [mental model](/guides/mental-model.md) guide to understand how the individual functions of Valibot's modular API work together.

## Coercion and defaults

Superstruct separates validation from coercion. Coercions and defaults defined with `coerce`, `defaulted` and `trimmed` are only applied when calling `create`, but not when calling `assert` or `is`. Valibot does not make this distinction. Transformations and default values are part of the schema and are always applied when parsing.

```ts
// Change this
const Schema = defaulted(trimmed(string()), 'foo');
const value = create(input, Schema);

// To this
const Schema = v.optional(v.pipe(v.string(), v.trim()), 'foo');
const value = v.parse(Schema, input);
```

For type coercions defined with `coerce`, use a pipeline with an explicit [`transform`](/api/transform.md) action or one of the dedicated transformation actions like [`toNumber`](/api/toNumber.md) or [`toDate`](/api/toDate.md).

```ts
// Change this
const Schema = coerce(number(), string(), (value) => parseFloat(value));

// To this
const Schema = v.pipe(v.string(), v.decimal(), v.toNumber());
```

## Change names

Most of the names are the same as in Superstruct. However, there are some exceptions. The following table shows all names that have changed.

| Superstruct    | Valibot                                                                                                                                                                                                   |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `assign`       | [Object merging](/guides/intersections.md#merge-objects)                                                                                                                                        |
| `coerce`       | [`pipe`](/api/pipe.md) and [`transform`](/api/transform.md)                                                                                                                 |
| `create`       | [`parse`](/api/parse.md)                                                                                                                                                                   |
| `defaulted`    | [`optional`](/api/optional.md)                                                                                                                                                             |
| `define`       | [`custom`](/api/custom.md)                                                                                                                                                                 |
| `dynamic`      | [`lazy`](/api/lazy.md)                                                                                                                                                                     |
| `enums`        | [`picklist`](/api/picklist.md)                                                                                                                                                             |
| `func`         | [`function`](/api/function.md)                                                                                                                                                             |
| `Infer`        | [`InferOutput`](/api/InferOutput.md)                                                                                                                                                       |
| `integer`      | [`number`](/api/number.md) with [`integer`](/api/integer.md)                                                                                                                |
| `intersection` | [`intersect`](/api/intersect.md)                                                                                                                                                           |
| `mask`         | [`parse`](/api/parse.md) with [`object`](/api/object.md)                                                                                                                    |
| `max`          | [`maxValue`](/api/maxValue.md), [`ltValue`](/api/ltValue.md)                                                                                                                |
| `min`          | [`minValue`](/api/minValue.md), [`gtValue`](/api/gtValue.md)                                                                                                                |
| `nonempty`     | [`nonEmpty`](/api/nonEmpty.md)                                                                                                                                                             |
| `object`       | [`strictObject`](/api/strictObject.md)                                                                                                                                                     |
| `pattern`      | [`regex`](/api/regex.md)                                                                                                                                                                   |
| `refine`       | [`check`](/api/check.md)                                                                                                                                                                   |
| `size`         | [`minLength`](/api/minLength.md), [`maxLength`](/api/maxLength.md), [`minValue`](/api/minValue.md), [`maxValue`](/api/maxValue.md) and others |
| `StructError`  | [`ValiError`](/api/ValiError.md)                                                                                                                                                           |
| `trimmed`      | [`trim`](/api/trim.md)                                                                                                                                                                     |
| `type`         | [`looseObject`](/api/looseObject.md)                                                                                                                                                       |
| `validate`     | [`safeParse`](/api/safeParse.md)                                                                                                                                                           |

## Other details

Below are some more details that may be helpful when migrating from Superstruct to Valibot.

### Unknown object keys

Superstruct provides three behaviors for unknown object keys, and each of them has a direct equivalent in Valibot. `object` rejects unknown keys, which matches [`strictObject`](/api/strictObject.md). `type` allows and keeps unknown keys, which matches [`looseObject`](/api/looseObject.md). The `mask` method removes unknown keys, which matches the default behavior of [`object`](/api/object.md) when parsing. See the [objects](/guides/objects.md) guide for more details.

```ts
// Change this
const value = mask(input, object({ key: string() }));

// To this
const value = v.parse(v.object({ key: v.string() }), input);
```

### Error details

Superstruct's `StructError` provides a `failures` method that returns all validation failures. In Valibot, the issues are directly available on the result of [`safeParse`](/api/safeParse.md) or via the `issues` property of a [`ValiError`](/api/ValiError.md). The [`flatten`](/api/flatten.md), [`summarize`](/api/summarize.md) and [`getDotPath`](/api/getDotPath.md) methods help you work with them. See the [issues](/guides/issues.md) guide for more details.

### Async validation

Superstruct does not support asynchronous validation. With Valibot, you get it for free. Functions like [`pipeAsync`](/api/pipeAsync.md) and [`checkAsync`](/api/checkAsync.md) allow you to run asynchronous logic, such as database checks, as part of your schema. See the [async guide](/guides/async-validation.md) for more details.
