Skip to main content

evolve()

evolve<T, Tr>(object, transformations): Evolved<T, Tr>

Applies transformations to an object in a declarative way.

๐Ÿ’Ž Why is this a Hidden Gem?

A distinctively declarative way to transform object properties using functions.

note

Properties without transformations are preserved.


Type Parametersโ€‹

T: T extends Record<string, unknown>โ€‹

The type of the input object.

Tr: Tr extends Transformations<T>โ€‹

The type of the transformations object.


Parametersโ€‹

object: Tโ€‹

The object to transform.

transformations: Trโ€‹

Object mapping property names to transformation functions.


Returns: Evolved<T, Tr>โ€‹

A new object with transformed values.


Sinceโ€‹

2.0.0


Noteโ€‹

Transformations for non-existent properties are ignored.


Noteโ€‹

Supports symbol keys via Reflect.ownKeys.


Performanceโ€‹

O(n) time & space where n is number of properties.


Also known asโ€‹

evolve (Remeda, Ramda) ยท โŒ (Lodash, es-toolkit, Radashi, Effect, Modern Dash, Antfu)


Exampleโ€‹

const user = { count: 1, name: 'tom', active: true };

evolve(user, { count: (x) => x + 1, name: (s) => s.toUpperCase() });
// => { count: 2, name: 'TOM', active: true }

// Nested transformations
evolve(
{ profile: { firstName: 'john', age: 25 } },
{ profile: { firstName: (s) => s.toUpperCase(), age: (n) => n + 1 } }
);
// => { profile: { firstName: 'JOHN', age: 26 } }

How it works?โ€‹

Applies transformations to an object in a declarative way. Properties without transformations are preserved unchanged.

Nested Transformationsโ€‹

evolve vs mapValuesโ€‹

evolvemapValues
Applies toSpecific keysAll keys
PreservesUntransformed keysN/A
NestedSupportedManual

Use Casesโ€‹

Transform specific fields ๐Ÿ“Œโ€‹

Apply different transformation functions to specific keys in an object. Perfect for normalizing data from API responses.

const user = evolve(apiResponse, {
name: (s) => s.trim(),
age: (n) => Number(n),
});

Apply nested transformationsโ€‹

Declaratively transform deeply nested properties. Essential for modifying complex state trees.

const state = evolve(appState, {
settings: {
theme: (t) => t.toLowerCase(),
notifications: (n) => !n // Toggle boolean
}
});

Sanitize data conditionallyโ€‹

Apply transformation logic that adapts to values. Useful for data cleaning pipelines.

const cleaned = evolve(data, {
score: (n) => (n < 0 ? 0 : n), // Clamp to 0
tags: (arr) => arr.filter(t => t.length > 0) // Remove empty tags
});

Evolved<T, Tr>โ€‹

Type

Evolved<T, Tr> = { [K in keyof T]: K extends keyof Tr ? Tr[K] extends (value: T[K]) => infer R ? R : Tr[K] extends Record<string, unknown> ? T[K] extends Record<string, unknown> ? Evolved<T[K], Tr[K]> : T[K] : T[K] : T[K] }

Type representing the result of applying transformations to an object.


Type Parametersโ€‹

T: Tโ€‹

Tr: Trโ€‹


Sinceโ€‹

2.0.0

Transformations<T>โ€‹

Type

Transformations<T> = { [K in keyof T]?: T[K] extends (args: unknown[]) => unknown ? (value: T[K]) => unknown : T[K] extends Record<string, unknown> ? Transformations<T[K]> | ((value: T[K]) => unknown) : (value: T[K]) => unknown }

Type representing transformation functions for each property.


Type Parametersโ€‹

T: Tโ€‹


Sinceโ€‹

2.0.0