> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/developer-guide-en/dev-start/images-and-media/validation-check.md).

# Validation Check

**The X2BEE solution** uses the **Zod library** to validate data. This guide explains how to efficiently implement schema definitions, per-field validation, full-object validation, data transformation, and type inference.

***

{% stepper %}
{% step %}

### How to Define a Zod Schema

Zod is a TypeScript-first schema declaration and validation library, used to eliminate duplicate type declarations. With Zod, you can validate data and infer TypeScript types.

{% code title="Example: basic object schema" %}

```javascript
import { z } from 'zod'

/** A basic zod object declaration can use the object function internally to create and return an object.
    Passing an object as the argument gives you a constant-form zod schema.
    For the object passed as the argument, you must define each field and specify its type using zod's types.
**/
const zodExampleSchema = z.object({
  name: z.string(),
  userId: z.string(),
  password: z.string(),
  phone: z.number()
})
```

{% endcode %}
{% endstep %}

{% step %}

### How to Validate Each Field

Since Zod alone has limits for some highly flexible validations, you can apply custom per-field validation using refine for each item. Below is a basic example, such as checking for an empty value.

{% code title="Example: field validation using refine" %}

```javascript
import { z } from 'zod'

/** There are various built-in validation methods such as min and max,
    but you can use zod's refine for more flexible validation.
    The first argument to refine is a function that returns whether validation passed (boolean),
    and the second argument is options such as the message.
**/
const zodExampleSchema = z.object({
  name: z.string().refine(
    (data) => !!data, // data refers to the value of the name field (returns boolean)
    {
      message: "이름을 입력해주세요."
    }
  ),
  userId: z.string(),
  password: z.string(),
  phone: z.number()
})
```

{% endcode %}
{% endstep %}

{% step %}

### How to Validate Across All Fields

Validation that requires referencing multiple fields (e.g., checking that a password and its confirmation match) is difficult to express with an individual field's refine, so superRefine is used at the object level. superRefine receives the entire data object and a context, letting you perform composite validation.

{% code title="Example: full-object validation using superRefine" %}

```javascript
import { z } from 'zod'

/** superRefine is a function applied to z.object.
    The first argument is an object holding all field data,
    and the second argument is zod's context (ctx).
**/
const zodExampleSchema = z.object({
  userId: z.string(),
  password: z.string(),
  rePassword: z.string()
}).superRefine((data, ctx) => {
  if (data.password !== data.rePassword) {
    ctx.addIssue({
      message: "비밀번호가 일치하지 않습니다.",
      code: z.ZodIssueCode.custom,
      path: ['password']
    })
    return false
  }
  return true
})
```

{% endcode %}
{% endstep %}

{% step %}

### How to Transform the Final Schema Data

Use transform when you need to process data at the schema level after validation — for example, converting the returned data or removing unnecessary fields. transform returns the object converted to its final value after validation passes. If needed, you can also process data before transform and validate it with superRefine.

{% code title="Example: superRefine + transform" %}

```javascript
import { z } from 'zod'

/** The example below checks that the ID is not empty, verifies the password confirmation,
    and then processes the final return value with transform.
**/
const zodExampleSchema = z.object({
  userId: z.string().refine(
    (data) => !!data,
    { message: "아이디를 입력해주세요." }
  ),
  password: z.string(),
  rePassword: z.string()
}).superRefine((data, ctx) => {
  if (data.password !== data.rePassword) {
    ctx.addIssue({
      message: "비밀번호가 일치하지 않습니다.",
      code: z.ZodIssueCode.custom,
      path: ['password']
    })
    return false
  }
  return true
}).transform((data) => {
  return {
    userId: data.userId,
    password: data.password
  }
})
```

{% endcode %}
{% endstep %}

{% step %}

### How to Infer Types

To infer a TypeScript type from a Zod schema, use z.infer.

{% code title="Example: type inference with z.infer" %}

```javascript
import { z } from 'zod'

/** TypeScript conversion example **/
const zodExampleSchema = z.object({
  // ...schema definition
})

// Typescript type
type zodExampleType = z.infer<typeof zodExampleSchema>
```

{% endcode %}
{% endstep %}
{% endstepper %}
