Skip to content

Why Choose farrow-schema?

🎯 Type Definition + Runtime Validation = Kill Two Birds with One Stone

💡 Make bugs nowhere to hide at both compile and runtime

Hey! 👋 If you've ever:

  • 😩 Written type definitions, then had to write validation logic again
  • 🤦 Received weird data in your API while TypeScript was powerless
  • 😭 Had to modify data structures in three places (types, validation, documentation)
  • 🥵 Been driven to collapse by product managers' "small changes"

Then farrow-schema is your savior!


Pain Points: The Dilemma of Traditional Approaches

Imagine you're developing a user registration feature. Using traditional methods, you need to:

typescript
// 1. Define TypeScript interface
interface User {
  name: string
  email: string
  age: number
}

// 2. Write validation function (start questioning your life choices)
function validateUser(data: any): User {
  if (!data.name || typeof data.name !== 'string') {
    throw new Error('Name is required and must be a string')
  }
  if (!data.email || !isValidEmail(data.email)) {
    throw new Error('Valid email is required')
  }
  if (!data.age || typeof data.age !== 'number') {
    throw new Error('Age is required and must be a number')
  }
  return data as User
}

// 3. Maintain synchronization of two definitions... 😭
// 4. Product manager: Can we add another field?
// 5. You: ... (mentally collapsing)

Problems are obvious:

  • ❌ Type definitions and validation logic are separate, easily inconsistent
  • ❌ Each modification requires synchronous updates to two places
  • ❌ Validation code is lengthy and repetitive, hard to maintain
  • ❌ TypeScript types are only effective at compile time

Solution: farrow-schema

Using farrow-schema, life suddenly becomes beautiful:

typescript
import { ObjectType, String, Number } from 'farrow-schema'
import { Validator } from 'farrow-schema/validator'

// One definition, simultaneously have types and validation
class User extends ObjectType {
  name = String
  email = EmailType  // Custom validator
  age = Number
}

// Automatically extract TypeScript types
type UserType = TypeOf<typeof User>
// { name: string, email: string, age: number }

// Runtime validation
const result = Validator.validate(User, req.body)
if (result.kind === 'Ok') {
  // result.value has passed validation, type-safe
  console.log(result.value)
}

Advantages:

  • One definition, dual protection - Compile-time type checking + runtime validation
  • Type inference - Automatically extract TypeScript types from Schema
  • Concise and elegant - Class inheritance, fits OOP habits
  • Easy to maintain - Modify one place, automatically sync

This is a third-party Farrow documentation site | Built with ❤️ and TypeScript