AbsoluteJS

Validation

Use Elysia schemas directly for request validation and end-to-end inferred types.

#Basics

Validate request bodies where the route is defined:

TS
import { Elysia, t } from 'elysia';

new Elysia()
  .post('/api/users', ({ body }) => createUser(body), {
    body: t.Object({
      name: t.String({ minLength: 2 }),
      email: t.String({ format: 'email' })
    })
  });

#Params & Query

Define params and query schema together to avoid untyped request parsing:

TS
import { Elysia, t } from 'elysia';

new Elysia()
  .get('/api/users/:id', ({ params, query }) => {
    return getUser(params.id, query.expand);
  }, {
    params: t.Object({
      id: t.String()
    }),
    query: t.Object({
      expand: t.Optional(t.Boolean())
    })
  });

#Typed Responses

Attach response schemas for status-specific return shapes:

TS
import { Elysia, t } from 'elysia';

new Elysia()
  .post('/api/projects', ({ body, set }) => {
    const project = createProject(body);
    set.status = 201;
    return project;
  }, {
    body: t.Object({
      name: t.String()
    }),
    response: {
      201: t.Object({
        id: t.String(),
        name: t.String()
      }),
      400: t.Object({
        error: t.String()
      })
    }
  });

#Guarded Validation

Use guard to enforce shared constraints for route groups:

TS
import { Elysia, t } from 'elysia';

new Elysia()
  .guard(
    {
      headers: t.Object({
        authorization: t.TemplateLiteral('Bearer ${string}')
      })
    },
    (app) =>
      app
        .get('/api/private/profile', ({ headers }) =>
          getProfile(headers.authorization)
        )
        .get('/api/private/settings', ({ headers }) =>
          getSettings(headers.authorization)
        )
  );

#References

Elysia Validation docs