or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-dot-prop

Get, set, or delete a property from a nested object using a dot path

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/dot-prop@9.0.x

To install, run

npx @tessl/cli install tessl/npm-dot-prop@9.0.0

index.mddocs/

dot-prop

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.

Package Information

  • Package Name: dot-prop
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install dot-prop

Core Imports

import { getProperty, setProperty, hasProperty, deleteProperty, escapePath, deepKeys } from "dot-prop";

For CommonJS:

const { getProperty, setProperty, hasProperty, deleteProperty, escapePath, deepKeys } = require("dot-prop");

Basic Usage

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");

Capabilities

Property Access

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');
// => undefined

Property Modification

Set 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'}}}]}

Property Existence

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');
// => false

Property Deletion

Delete 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)

Path Escaping

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 traversal

Deep Key Extraction

Extract 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);
}

Path Syntax

dot-prop supports flexible path syntax for accessing nested properties:

Dot Notation

  • Basic: 'user.name' - accesses object.user.name
  • Deep nesting: 'user.profile.settings.theme' - accesses deeply nested properties

Array Indexing

  • Numeric index: 'users[0]' - accesses first element
  • Mixed syntax: 'users[0].name' - accesses property of array element
  • Nested arrays: 'matrix[0][1]' - accesses nested array elements

Escaped Characters

  • Literal dots: 'user.dot\\.dot' - accesses property named "dot.dot"
  • Literal brackets: 'user.arr\\[0\\]' - accesses property named "arr[0]"

Security Features

  • Dangerous properties: Paths containing __proto__, prototype, or constructor return undefined
  • String index validation: Prevents array mutation through string indexes
  • Path validation: Invalid path syntax throws descriptive errors

Error Handling

dot-prop provides robust error handling and validation:

Path Parsing Errors

// Invalid array index syntax
getProperty(obj, 'items[abc]'); // Throws: "Invalid character in an index"
getProperty(obj, 'items[0'); // Throws: "Index was not closed"

Type Validation

// escapePath requires string input
escapePath(123); // Throws: TypeError("Expected a string")

Safe Operations

// 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

Types

// 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>;