Transformation
Transformation functions allow you to systematically transform or filter object keys and values. These operations are essential for normalizing data, applying bulk transformations, and filtering unwanted properties.
Table of Contents
mapKeys
Transform all keys in an object using a mapping function.
function mapKeys<T extends PlainObject>(
obj: T,
fn: (key: string, value: T[keyof T]) => string
): PlainObjectReal-World: snake_case → camelCase
// API response normalization
const apiResponse = {
user_id: 123,
first_name: 'Alice',
last_name: 'Smith',
email_address: 'alice@example.com',
created_at: '2024-01-01'
}
const normalized = mapKeys(apiResponse, (key) =>
key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
)
// { userId: 123, firstName: 'Alice', lastName: 'Smith', ... }For the common conventions, transformKeys(apiResponse, 'camelCase') does this for you, nested objects included.
Real-World: Prefixing for Namespacing
// Add namespace to avoid conflicts
const config = { host: 'localhost', port: 5432 }
const namespaced = mapKeys(config, (key) => `db_${key}`)
// => { db_host: 'localhost', db_port: 5432 }Conditional Transformation
// Transform only numeric values' keys
mapKeys(data, (key, value) =>
typeof value === 'number' ? key.toUpperCase() : key
)mapValues
Transform all values in an object using a mapping function.
function mapValues<T extends PlainObject, U>(
obj: T,
fn: (value: T[keyof T], key: keyof T) => U
): Record<keyof T, U>Real-World: Price Calculations
const prices = {
apple: 1.50,
banana: 0.50,
orange: 2.00
}
// Apply 10% tax
const withTax = mapValues(prices, (price) =>
Math.round(price * 1.1 * 100) / 100
)
// => { apple: 1.65, banana: 0.55, orange: 2.2 }Real-World: Type Conversions
// Convert all values to strings
const config = { port: 5432, timeout: 30000, retries: 3 }
const envVars = mapValues(config, (v) => String(v))
// => { port: '5432', timeout: '30000', retries: '3' }Access Key in Transformation
const user = { name: 'Alice', age: 30 }
// Format with key context
mapValues(user, (value, key) => `${String(key)}: ${value}`)
// => { name: 'name: Alice', age: 'age: 30' }filterKeys
Filter object by keeping only keys that match a predicate.
function filterKeys<T extends PlainObject>(
obj: T,
predicate: (key: string) => boolean
): Partial<T>Real-World: Remove Private Fields
const obj = {
id: 1,
name: 'Alice',
_internal: 'hidden',
_cache: {},
email: 'alice@example.com'
}
const visible = filterKeys(obj, (key) => !key.startsWith('_'))
// => { id: 1, name: 'Alice', email: 'alice@example.com' }Real-World: Extract by Pattern
// Get only API-related config
const config = {
api_key: 'secret',
api_url: 'https://api.com',
api_timeout: 30000,
db_host: 'localhost',
db_port: 5432
}
const apiConfig = filterKeys(config, (key) => key.startsWith('api_'))
// => { api_key: 'secret', api_url: 'https://api.com', api_timeout: 30000 }filterValues
Filter object by keeping only entries whose values match a predicate.
function filterValues<T extends PlainObject>(
obj: T,
predicate: (value: T[keyof T], key: keyof T) => boolean
): Partial<T>Real-World: Filter by Score Threshold
const scores = {
alice: 95,
bob: 65,
charlie: 88,
diana: 72
}
const passing = filterValues(scores, (score) => score >= 70)
// => { alice: 95, charlie: 88, diana: 72 }Real-World: Remove Empty Values
const formData = {
name: 'Alice',
email: '',
phone: '',
company: 'Acme Inc'
}
const filled = filterValues(formData, (v) => v !== '')
// => { name: 'Alice', company: 'Acme Inc' }With Key Context
// Filter based on key-value relationship
filterValues(inventory, (qty, product) =>
String(product).startsWith('premium_') ? qty > 10 : qty > 0
)Comparison
| Function | Transforms | Use Case |
|---|---|---|
mapKeys | All keys | Custom renames, prefixing |
transformKeys | All keys, at every depth | Normalize naming (camelCase, snake_case) |
mapValues | All values | Calculations, type conversions |
filterKeys | Keys (keep matching) | Remove private/internal fields |
filterValues | Values (keep matching) | Threshold filtering, remove empty |
Combined Example
// Complete transformation pipeline
const process = (apiData: PlainObject) =>
pipe(
apiData,
filterKeys((key) => !key.startsWith('_')), // Remove private
transformKeys('camelCase'), // Normalize keys
mapValues((v) => typeof v === 'string' ? v.trim() : v), // Trim strings
filterValues((v) => v != null), // Remove nullish
compact // Final cleanup
)Next Steps
- Patterns & Recipes - Real-world solutions
- Migration Guide - From Lodash to Receta
- API Reference - Quick lookup
Validation
Validation functions ensure data integrity through runtime type checking and cleanup operations. These utilities help you validate unknown data, remove unwanted values, and ensure objects meet expected schemas.
Patterns & Recipes
Copy-paste ready patterns for common real-world scenarios. All examples are production-ready and based on actual API structures.