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
