CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-map-obj

Map object keys and values into a new object

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Map Object

Map Object provides a utility function for mapping object keys and values into new objects, supporting both shallow and deep transformation of nested structures. It offers a flexible mapper function that allows developers to rename keys, transform values, and selectively exclude properties using a special skip symbol, with built-in support for recursive processing of nested objects and arrays while maintaining proper circular reference handling.

Package Information

  • Package Name: map-obj
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install map-obj

Core Imports

import mapObject, { mapObjectSkip } from "map-obj";

For CommonJS:

const mapObject = require("map-obj");
const { mapObjectSkip } = require("map-obj");

Basic Usage

import mapObject, { mapObjectSkip } from "map-obj";

// Transform keys and values
const result = mapObject({ foo: "bar" }, (key, value) => [value, key]);
// Result: { bar: "foo" }

// Transform keys (e.g., normalize case)
const normalized = mapObject(
  { FOO: true, bAr: { bAz: true } },
  (key, value) => [key.toLowerCase(), value]
);
// Result: { foo: true, bar: { bAz: true } }

// Deep transformation
const deepNormalized = mapObject(
  { FOO: true, bAr: { bAz: true } },
  (key, value) => [key.toLowerCase(), value],
  { deep: true }
);
// Result: { foo: true, bar: { baz: true } }

// Exclude properties using skip symbol
const filtered = mapObject(
  { one: 1, two: 2 },
  (key, value) => (value === 1 ? [key, value] : mapObjectSkip)
);
// Result: { one: 1 }

Capabilities

Map Object Function

Maps object keys and values into a new object using a provided mapper function.

/**
 * Map object keys and values into a new object
 * @param source - The source object to copy properties from
 * @param mapper - A mapping function that transforms keys and values
 * @param options - Optional configuration for mapping behavior
 * @returns New object with mapped keys and values
 */
function mapObject<
  SourceObjectType extends Record<string, unknown>,
  TargetObjectType extends Record<string, any>,
  MappedObjectKeyType extends string,
  MappedObjectValueType,
>(
  source: SourceObjectType,
  mapper: Mapper<SourceObjectType, MappedObjectKeyType, MappedObjectValueType>,
  options: DeepOptions & TargetOptions<TargetObjectType>
): TargetObjectType & Record<string, unknown>;

function mapObject<
  SourceObjectType extends Record<string, unknown>,
  MappedObjectKeyType extends string,
  MappedObjectValueType,
>(
  source: SourceObjectType,
  mapper: Mapper<SourceObjectType, MappedObjectKeyType, MappedObjectValueType>,
  options: DeepOptions
): Record<string, unknown>;

function mapObject<
  SourceObjectType extends Record<string, any>,
  TargetObjectType extends Record<string, any>,
  MappedObjectKeyType extends string,
  MappedObjectValueType,
>(
  source: SourceObjectType,
  mapper: Mapper<SourceObjectType, MappedObjectKeyType, MappedObjectValueType>,
  options: TargetOptions<TargetObjectType>
): TargetObjectType & {[K in MappedObjectKeyType]: MappedObjectValueType};

function mapObject<
  SourceObjectType extends Record<string, any>,
  MappedObjectKeyType extends string,
  MappedObjectValueType,
>(
  source: SourceObjectType,
  mapper: Mapper<SourceObjectType, MappedObjectKeyType, MappedObjectValueType>,
  options?: Options
): {[K in MappedObjectKeyType]: MappedObjectValueType};

Usage Examples:

// Key transformation
const camelCased = mapObject(
  { "first-name": "John", "last-name": "Doe" },
  (key, value) => [key.replace(/-(\w)/g, (_, char) => char.toUpperCase()), value]
);
// Result: { firstName: "John", lastName: "Doe" }

// Value transformation
const doubled = mapObject(
  { a: 1, b: 2, c: 3 },
  (key, value) => [key, value * 2]
);
// Result: { a: 2, b: 4, c: 6 }

// Using target option
const target = { existing: "value" };
const merged = mapObject(
  { new: "data" },
  (key, value) => [key, value],
  { target }
);
// Result: target object is modified and returned

Map Object Skip Symbol

Special symbol returned from a mapper function to exclude a key from the result object.

/**
 * Return this value from a mapper function to remove a key from an object
 */
const mapObjectSkip: unique symbol;

Usage Examples:

import mapObject, { mapObjectSkip } from "map-obj";

// Conditional inclusion
const adults = mapObject(
  { alice: 25, bob: 16, charlie: 30 },
  (key, value) => (value >= 18 ? [key, value] : mapObjectSkip)
);
// Result: { alice: 25, charlie: 30 }

// Property filtering based on key patterns
const publicProps = mapObject(
  { name: "John", _private: "secret", age: 30, _id: 123 },
  (key, value) => (key.startsWith("_") ? mapObjectSkip : [key, value])
);
// Result: { name: "John", age: 30 }

Types

Mapper Function Type

type Mapper<
  SourceObjectType extends Record<string, any>,
  MappedObjectKeyType extends string,
  MappedObjectValueType,
> = (
  sourceKey: keyof SourceObjectType,
  sourceValue: SourceObjectType[keyof SourceObjectType],
  source: SourceObjectType
) => [
  targetKey: MappedObjectKeyType,
  targetValue: MappedObjectValueType,
  mapperOptions?: MapperOptions,
] | typeof mapObjectSkip;

Options Interface

interface Options {
  /**
   * Recurse nested objects and objects in arrays
   * @default false
   */
  readonly deep?: boolean;

  /**
   * The target object to map properties on to
   * @default {}
   */
  readonly target?: Record<string, any>;
}

Deep Options Interface

interface DeepOptions extends Options {
  readonly deep: true;
}

Target Options Interface

interface TargetOptions<TargetObjectType extends Record<string, any>> extends Options {
  readonly target: TargetObjectType;
}

Mapper Options Interface

interface MapperOptions {
  /**
   * Whether targetValue should be recursed
   * Requires deep: true
   * @default true
   */
  readonly shouldRecurse?: boolean;
}

Advanced Usage

Deep Object Mapping

const nested = {
  user: {
    profile: {
      firstName: "John",
      lastName: "Doe"
    },
    preferences: ["email", "sms"]
  }
};

const normalized = mapObject(
  nested,
  (key, value) => [key.toLowerCase(), value],
  { deep: true }
);
// All nested keys are transformed recursively

Selective Recursion Control

const data = {
  metadata: { version: "1.0", author: "John" },
  content: { title: "Example", body: "Content here" }
};

const result = mapObject(
  data,
  (key, value) => {
    if (key === "metadata") {
      // Don't recurse into metadata
      return [key, value, { shouldRecurse: false }];
    }
    return [key.toUpperCase(), value];
  },
  { deep: true }
);
// metadata object is not recursively transformed

Circular Reference Handling

const obj = { name: "test" };
obj.self = obj; // Create circular reference

const mapped = mapObject(
  obj,
  (key, value) => [key.toUpperCase(), value],
  { deep: true }
);
// Circular references are handled automatically using WeakMap tracking

Error Handling

The mapObject function validates its input and throws TypeError in the following cases:

  • When the first argument is not an object: TypeError: Expected an object, got \value` (type)`
  • When the first argument is an array: TypeError: Expected an object, got an array
try {
  mapObject(null, (k, v) => [k, v]);
} catch (error) {
  console.log(error.message); // "Expected an object, got `null` (object)"
}

try {
  mapObject([1, 2, 3], (k, v) => [k, v]);
} catch (error) {
  console.log(error.message); // "Expected an object, got an array"
}

docs

index.md

tile.json