🎯 Sets the value at a specific path of an object.
Mutable: This function mutates the original object. Use toSet for an immutable version.
Syntax
import { set } from '@opentf/std'; set<T>( obj: T, path: string | unknown[], value: unknown | ((val: unknown) => unknown) ): T
Parameters
obj: The object to modify.path: The path of the property to set.value: The value to set, or a callback function that receives the current value and returns the new value.
Returns
The modified object.
Behavior
Missing intermediate branches are created automatically.
Existing non-object intermediates such as
0,false,'', andnullare preserved. Deep writes through those values are ignored instead of overwriting them.
__proto__, constructor and prototype are refused as path segments. The path is checked before anything is written, so a path that will be refused leaves the object exactly as it was — no partial branch.
A numeric segment creates an array only up to MAX_ARRAY_INDEX (10,000). Above that the branch becomes a plain object keyed by the number, so the value is kept and only the array-ness is dropped.
A lone large index in untrusted input would otherwise build an array whose length makes serialising the result cost hundreds of megabytes. A flattened array starts at [0], so one of any size still round trips.
Examples
set({}, 'a', 1) //=> { a: 1 } set({}, 'a.b', 25) //=> { a: { b: 25 } } set({}, 'user.email', 'user@example.com') //=> { user: { email: 'user@example.com' } } set({}, 'fruits[0]', 'Apple') //=> { fruits: ['Apple'] } // Using a callback to update based on current value set({ a: 1 }, 'a', (val) => val + 1) //=> { a: 2 } // Automatically creates arrays if indices are used in path set({}, 'items[2].id', 1) //=> { items: [undefined, undefined, { id: 1 }] } // Existing falsy non-object intermediates are not replaced set({ a: 0 }, 'a.b', 1) //=> { a: 0 }