← Back to list

Validating data schema effectively with Effect-TS

Effect-TS is a great library to leverage the benefits of functional programming in TypeScript. It also provides powerful tools for defining…

AYAN PAL · 2025-03-08 17:52 · 2 claps · 2.5 min read
#effect-ts #typescript #schema-validation #data-schema
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval CRY · Crypto & Web3 💻 · Programming 🌐 · Web Development 💑 · Relationships 📚 · Books & Reading

Validating data schema effectively with Effect-TS

***Effect-TS*** is a great library to leverage the benefits of functional programming in TypeScript. It also provides powerful tools for defining and validating data structures, ensuring your application handles data correctly.

1. Introduction

Effect-TS leverages the power of TypeScript’s type system along with runtime validation to create robust data validation. We assume here that the readers of this post are already familiar with the basic understanding of TypeScript, and Effect-TS concepts (e.g., Effect, Schema).

2. Defining Schemas

Schemas define the structure and constraints of your data. Effect-TS provides various schema constructors for different data types.

Example: Defining a user schema:

import { Schema } from 'effect';

type User = {
  id: number;
  name: string;
  email: string;
  age?: number | undefined;
}

const UserSchema = Schema.struct({
  id: Schema.Number,
  name: Schema.NonEmptyString,
  email: Schema.NonEmptyString,
  age: Schema.optional(Schema.number), // Optional field
});

// We can also infer TypeScript type from schema
type Type = S.Schema.Type<typeof User>;
// type Type = {
//   id: number;
//   name: string;
//   email: string;
//   age?: number | undefined;
// }

3. Schema Constructors

Several ready-to-use Schema constructors are available in Effect-TS like the following:

  • Schema.String: Defines a string schema.
  • Schema.Number: Defines a number schema.
  • Schema.Boolean: Defines a boolean schema.
  • Schema.Struct({ ... }): Defines an object schema.
  • Schema.Array(schema): Defines an array schema.
  • Schema.Union(schema1, schema2, ...): Defines a union schema (allowing multiple types).
  • Schema.optional(schema): Makes a field optional.
  • Schema.Literal("value"): Defines a literal schema (specific value).
  • Schema.Enums({ ... }): Defines an enumeration schema.

4. Validating Data

Use Schema.decodeSync() to validate data against a schema.

Example: Validating a user object:

import { Schema } from 'effect';

const UserSchema = Schema.struct({
  id: Schema.Number,
  name: Schema.NonEmptyString,
  email: Schema.NonEmptyString,
  age: Schema.optional(Schema.number), // Optional field
});

const userData = {
  id: 12345,
  name: 'Bob',
  email: 'bob@mydomain.com',
  age: 20,
};

const validateData = <T>(data: T, schema: Schema.Schema<T, T, unknown>) => {
  let isDataValid = false;
  try {
    const validatorFunc = Schema.decodeSync<T, T>(schema as never);
    validatorFunc(data);
    isDataValid = true;
  } catch (error) {
    console.log(`Data is not valid. Reason: ${error}`);
  }
  return isDataValid;
};

const isValid = validateData(userData, userSchema);
console.log(`Is user data valid? ${isValid}`);

5. Advanced Schema Features

  • Add custom validation logic:
import { Schema } from 'effect';

// Starts with A, B, C or D, followed by '_', followed by one or more digits.
// Like: A_2309, C_030755
const ID_PATTERN = /^[A-D]_[0-9]+$/;

const positiveIntFilter = Schema.filter((i) => {
  if (i && (i as number) > 0) {
    return true;
  } else {
    return `Given value (${i}) ius not a non-negative integer`;
  }
});

const dateFilter = Schema.filter((dt) => {
  if (dt && !isNaN(new Date(dt as string).getTime())) {
    return true;
  } else {
    return `Given value (${dt}) is not a valid date`;
  }
});

const UserSchema = Schema.struct({
  id: Schema.String.pipe(Schema.pattern(ID_PATTERN)),
  name: Schema.NonEmptyString,
  email: Schema.NonEmptyString,
  age: Schema.Int.pipe(positiveIntFilter),
  dob: Schema.NonEmptyString.pipe(dateFilter),
});

const userData = {
  id: B_12345,
  name: 'Bob',
  email: 'bob@mydomain.com',
  age: 20,
  dob: '2005-10-15',
};

const validateData = <T>(data: T, schema: Schema.Schema<T, T, unknown>) => {
  let isDataValid = false;
  try {
    const validatorFunc = Schema.decodeSync<T, T>(schema as never);
    validatorFunc(data);
    isDataValid = true;
  } catch (error) {
    console.log(`Data is not valid. Reason: ${error}`);
  }
  return isDataValid;
};

const isValid = validateData(userData, userSchema);
console.log(`Is user data valid? ${isValid}`);

6. Best Practices

  • Define schemas close to your data sources.
  • Use refinements and transformations to enforce business logic.
  • Write comprehensive tests for your schemas.
  • Use meaningful error messages.

7. Conclusion

Effect-TS’s schema validation provides a powerful and type-safe way to ensure data integrity in your applications. By following the guidelines in this manual, you can effectively define and validate data schemas, leading to more robust and reliable code.

8. References

Further reading: https://effect.website/docs/schema/introduction/


메타데이터
post_id
9bba747fc025
slug
validating-data-schema-effectively-with-effect-ts-9bba747fc025
url
https://medium.com/@ayan.technocrat/validating-data-schema-effectively-with-effect-ts-9bba747fc025
canonical_url
https://medium.com/@ayan.technocrat/validating-data-schema-effectively-with-effect-ts-9bba747fc025
author_url
https://medium.com/@ayan.technocrat
status
ok
fetched_at
2026-06-26 03:39:16