← Back to utilities
object

has-path

Checks if a nested property path exists in an object. Safely traverses nested object properties using a dot-notation path string or an array of keys. Returns true if the path exists (even if the final value is undefined), false if any part of the path is missing.

Installation

npx fragmen add object/has-path

Source Code

/**
 * Checks if a nested property path exists in an object.
 *
 * Safely traverses nested object properties using a dot-notation path string
 * or an array of keys. Returns true if the path exists (even if the final value
 * is undefined), false if any part of the path is missing.
 *
 * @tags pure, validation
 * @param {object} obj The object to check
 * @param {string | string[]} path The property path as a string (dot notation) or array of keys
 * @returns {boolean} True if the path exists, false otherwise
 *
 * @example
 * ```typescript
 * const user = {
 *   name: 'John',
 *   address: {
 *     street: '123 Main St',
 *     city: 'NYC',
 *     coordinates: {
 *       lat: 40.7128,
 *       lng: undefined
 *     }
 *   }
 * };
 *
 * hasPath(user, 'name'); // true
 * hasPath(user, 'address.city'); // true
 * hasPath(user, 'address.coordinates.lat'); // true
 * hasPath(user, 'address.coordinates.lng'); // true (exists but undefined)
 * hasPath(user, 'address.zipcode'); // false
 * hasPath(user, 'nonexistent'); // false
 *
 * // Using array notation
 * hasPath(user, ['address', 'coordinates', 'lat']); // true
 * hasPath(user, ['address', 'zipcode']); // false
 *
 * // Works with arrays
 * const data = { items: [{ id: 1 }, { id: 2 }] };
 * hasPath(data, 'items.0.id'); // true
 * hasPath(data, 'items.2.id'); // false
 * ```
 */
export function hasPath(
  obj: Record<string, unknown> | null | undefined,
  path: string | (string | number)[]
): boolean {
  // Handle edge cases
  if (!obj || typeof obj !== 'object') {
    return false;
  }

  // Convert string path to array
  const keys = typeof path === 'string' ? path.split('.') : path;

  if (!Array.isArray(keys) || keys.length === 0) {
    return false;
  }

  let current: unknown = obj;

  for (const key of keys) {
    // Check if current is an object or array
    if (!current || typeof current !== 'object') {
      return false;
    }

    // Check if key exists in current object/array
    if (!(String(key) in current)) {
      return false;
    }

    // Move to next level
    current = (current as Record<string, unknown>)[String(key)];
  }

  return true;
}

Examples

const user = {
  name: 'John',
  address: {
    street: '123 Main St',
    city: 'NYC',
    coordinates: {
      lat: 40.7128,
      lng: undefined
    }
  }
};

hasPath(user, 'name'); // true
hasPath(user, 'address.city'); // true
hasPath(user, 'address.coordinates.lat'); // true
hasPath(user, 'address.coordinates.lng'); // true (exists but undefined)
hasPath(user, 'address.zipcode'); // false
hasPath(user, 'nonexistent'); // false

// Using array notation
hasPath(user, ['address', 'coordinates', 'lat']); // true
hasPath(user, ['address', 'zipcode']); // false

// Works with arrays
const data = { items: [{ id: 1 }, { id: 2 }] };
hasPath(data, 'items.0.id'); // true
hasPath(data, 'items.2.id'); // false

Related Utilities

clone

object

Creates a deep copy of an object. Recursively clones all properties of an object, including nested objects and arrays. Handles circular references by maintaining a reference map. Primitive values, functions, and built-in objects like Date and RegExp are handled appropriately.

#pure#object-manipulation

omit

object

Creates a new object by omitting specified keys from the source object. Returns a new object that contains all properties from the source object except for the specified keys. This is the opposite of the pick utility. The operation is shallow - nested objects are not deeply omitted.

#pure#object-manipulation

pick

object

Creates a new object composed of the picked object properties. Extracts only the specified keys from the source object, creating a new object with just those properties. Non-existent keys are silently ignored.

#pure#object-manipulation

is-falsy

boolean

Checks if a value is falsy. Returns true for JavaScript falsy values: false, 0, -0, 0n, "", null, undefined, and NaN. Useful for type-safe falsy checks and filtering operations.

#pure#validation#type-checking

is-truthy

boolean

Checks if a value is truthy. Returns true for all JavaScript truthy values (anything that is not falsy). Complementary function to isFalsy, useful for filtering and validation.

#pure#validation#type-checking

safe-parse

json

Safely parses a JSON string, returning undefined if parsing fails. Provides error-safe JSON parsing without throwing exceptions. Useful when working with untrusted input or when you want to handle parsing failures gracefully rather than with try-catch blocks.

#pure#validation

Quick Actions

Estimated size:2.10 KB

Tags

Parameters

objobject

The object to check

pathstring | string[]

The property path as a string (dot notation) or array of keys

Returns

boolean

True if the path exists, false otherwise