dot-prop is a lightweight utility library for manipulating nested object properties using dot notation paths. It provides safe and intuitive operations for getting, setting, checking, and deleting properties in deeply nested JavaScript objects and arrays.
npm install dot-propimport { getProperty, setProperty, hasProperty, deleteProperty, escapePath, deepKeys } from "dot-prop";For CommonJS:
const { getProperty, setProperty, hasProperty, deleteProperty, escapePath, deepKeys } = require("dot-prop");import { getProperty, setProperty, hasProperty, deleteProperty } from "dot-prop";
const data = {
user: {
profile: {
name: "Alice",
settings: {
theme: "dark"
}
},
posts: [
{ title: "Hello World", published: true }
]
}
};
// Get nested values
const name = getProperty(data, "user.profile.name");
// => "Alice"
const firstPostTitle = getProperty(data, "user.posts[0].title");
// => "Hello World"
// Set nested values (mutates original object)
setProperty(data, "user.profile.bio", "Software developer");
setProperty(data, "user.posts[0].views", 150);
// Check if property exists
const hasTheme = hasProperty(data, "user.profile.settings.theme");
// => true
// Delete properties
deleteProperty(data, "user.profile.settings.theme");Get values from nested objects using dot notation paths.
/**
* Get the value of the property at the given path
* @param object - Object or array to get the path value from
* @param path - Path of the property using dot notation
* @param defaultValue - Default value if path doesn't exist
* @returns Property value or defaultValue if not found
*/
function getProperty<ObjectType, PathType extends string, DefaultValue = undefined>(
object: ObjectType,
path: PathType,
defaultValue?: DefaultValue
): ObjectType extends Record<string, unknown> | unknown[]
? (unknown extends Get<ObjectType, PathType> ? DefaultValue : Get<ObjectType, PathType>)
: undefined;Usage Examples:
import { getProperty } from "dot-prop";
// Basic property access
getProperty({foo: {bar: 'unicorn'}}, 'foo.bar');
// => 'unicorn'
// Array indexing
getProperty({users: [{name: 'Alice'}, {name: 'Bob'}]}, 'users[1].name');
// => 'Bob'
// Default values for missing properties
getProperty({foo: {bar: 'a'}}, 'foo.missing.deep', 'default value');
// => 'default value'
// Escaped dots in property names
getProperty({foo: {'dot.dot': 'unicorn'}}, 'foo.dot\\.dot');
// => 'unicorn'
// Handles null/undefined gracefully
getProperty(null, 'any.path');
// => undefinedSet values at nested object paths, creating intermediate objects and arrays as needed.
/**
* Set the property at the given path to the given value
* @param object - Object or array to set the path value
* @param path - Path of the property using dot notation
* @param value - Value to set at path
* @returns The modified object
*/
function setProperty<ObjectType extends Record<string, any>>(
object: ObjectType,
path: string,
value: unknown
): ObjectType;Usage Examples:
import { setProperty } from "dot-prop";
// Basic property setting
const obj = {foo: {bar: 'a'}};
setProperty(obj, 'foo.bar', 'b');
// obj is now {foo: {bar: 'b'}}
// Creating nested structure
const result = setProperty({}, 'user.profile.name', 'Alice');
// => {user: {profile: {name: 'Alice'}}}
// Array creation and indexing
setProperty(obj, 'items[0]', 'first item');
// Creates array at 'items' and sets first element
// Mixed object and array paths
setProperty({}, 'users[0].profile.settings.theme', 'dark');
// => {users: [{profile: {settings: {theme: 'dark'}}}]}Check whether a property exists at the given path.
/**
* Check whether the property at the given path exists
* @param object - Object or array to test the path value
* @param path - Path of the property using dot notation
* @returns Boolean indicating property existence
*/
function hasProperty(object: Record<string, any> | undefined, path: string): boolean;Usage Examples:
import { hasProperty } from "dot-prop";
const data = {
user: {
name: "Alice",
posts: [
{ title: "Hello" }
]
}
};
hasProperty(data, 'user.name');
// => true
hasProperty(data, 'user.posts[0].title');
// => true
hasProperty(data, 'user.email');
// => false
// Handles null/undefined objects
hasProperty(null, 'any.path');
// => falseDelete properties at nested paths.
/**
* Delete the property at the given path
* @param object - Object or array to delete the path value
* @param path - Path of the property using dot notation
* @returns Boolean indicating if property existed before deletion
*/
function deleteProperty(object: Record<string, any>, path: string): boolean;Usage Examples:
import { deleteProperty } from "dot-prop";
const data = {
user: {
name: "Alice",
email: "alice@example.com",
settings: {
theme: "dark",
notifications: true
}
}
};
// Delete nested property
deleteProperty(data, 'user.settings.theme');
// => true (property existed and was deleted)
// data.user.settings is now {notifications: true}
// Delete array element
const arrayData = {items: ['a', 'b', 'c']};
deleteProperty(arrayData, 'items[1]');
// => true
// arrayData.items is now ['a', undefined, 'c']
// Attempt to delete non-existent property
deleteProperty(data, 'user.nonexistent');
// => false (property didn't exist)Escape special characters in paths for literal property names.
/**
* Escape special characters in a path
* @param path - The dot path to sanitize
* @returns Escaped path string
*/
function escapePath(path: string): string;Usage Examples:
import { getProperty, escapePath } from "dot-prop";
const object = {
foo: {
bar: 'πΈπ» You found me Mario!',
},
'foo.bar': 'π The princess is in another castle!',
};
// Without escaping - accesses nested property
getProperty(object, 'foo.bar');
// => 'πΈπ» You found me Mario!'
// With escaping - accesses literal property name
const escapedPath = escapePath('foo.bar');
getProperty(object, escapedPath);
// => 'π The princess is in another castle!'
// Useful for user input sanitization
const userInput = 'user.settings.theme';
const safePath = escapePath(userInput);
// Ensures literal property access instead of path traversalExtract all possible paths from an object as an array of dot-notation strings.
/**
* Returns an array of every path in the object
* @param object - The object to iterate through
* @returns Array of all dot-notation paths in object
*/
function deepKeys(object: unknown): string[];Usage Examples:
import { deepKeys, getProperty } from "dot-prop";
const user = {
name: {
first: 'Alice',
last: 'Smith',
},
posts: [
{ title: 'Hello World', published: true },
{ title: 'Goodbye', published: false }
],
settings: {
theme: 'dark'
}
};
const allPaths = deepKeys(user);
// => [
// 'name.first',
// 'name.last',
// 'posts[0].title',
// 'posts[0].published',
// 'posts[1].title',
// 'posts[1].published',
// 'settings.theme'
// ]
// Iterate over all properties
for (const path of deepKeys(user)) {
console.log(`${path}: ${getProperty(user, path)}`);
}
// Useful for flattening objects for APIs
const flattened = {};
for (const path of deepKeys(user)) {
flattened[path] = getProperty(user, path);
}dot-prop supports flexible path syntax for accessing nested properties:
'user.name' - accesses object.user.name'user.profile.settings.theme' - accesses deeply nested properties'users[0]' - accesses first element'users[0].name' - accesses property of array element'matrix[0][1]' - accesses nested array elements'user.dot\\.dot' - accesses property named "dot.dot"'user.arr\\[0\\]' - accesses property named "arr[0]"__proto__, prototype, or constructor return undefineddot-prop provides robust error handling and validation:
// Invalid array index syntax
getProperty(obj, 'items[abc]'); // Throws: "Invalid character in an index"
getProperty(obj, 'items[0'); // Throws: "Index was not closed"// escapePath requires string input
escapePath(123); // Throws: TypeError("Expected a string")// Operations on null/undefined objects return safe defaults
getProperty(null, 'any.path'); // => undefined
hasProperty(undefined, 'any.path'); // => false
setProperty(null, 'any.path', 'value'); // => null (no-op)
deleteProperty(null, 'any.path'); // => false// Imported from type-fest dependency for path-based type inference
import { type Get } from 'type-fest';
// Get<ObjectType, PathType> provides compile-time type safety by inferring
// the return type based on the object structure and dot-notation path
type GetType<ObjectType, PathType extends string> = Get<ObjectType, PathType>;