Skip to content

Simplify an object tree with a shortcut. TypeScript supported.

License

Notifications You must be signed in to change notification settings

papb/tree-shortcut

Repository files navigation

tree-shortcut Build Status install size

Simplify an object tree with a shortcut. TypeScript supported.

Install

$ npm install tree-shortcut

Purpose

This module allows you to simplify a tree structure (i.e., any recursive object/array structure) by replacing objects with the value of one of its keys.

For example, you may want to convert [{ a: 1, b: 2 }, { a: 3, d: 4 }] into [1, 3] (replacing each object by its value on 'a').

This module provides a treeShortcut function that takes a tree and a simple shortcut description and returns a deeply-cloned tree with a little change: the nested access of your choice is replaced by a shortcut. This allows you to simplify a complex tree of data, skipping information that you do not need.

The shortcut description is a set of three strings:

  • shortcutTriggerProp: The name of the property in which the shortcut begins
  • shortcutTargetProp: The name of the nested property, target of the shortcut
  • shortcutName: The name of the new property that will replace shortcutTriggerProp, whose value will be the one of the target property.

The provided object is unchanged.

The example below will make this clear.

You can also read the detailed algorithm description if you want.

Example

const treeShortcut = require('tree-shortcut');

const tree = {
    items: [
        {
            foo: { bar: [1, 2, 3] },
        },
        {
            foo: { bar: [4, 5], baz: true },
        },
        {
            foo: { baz: false },
        },
        {
            foo: null,
        },
    ],
};

const newTree = treeShortcut(tree, 'foo', 'bar', 'foobar');

console.log(newTree);
//=> {
//     items: [
//         {
//             foobar: [1, 2, 3]
//         },
//         {
//             foobar: [4, 5]
//         },
//         {
//             foobar: undefined
//         },
//         {
//             foobar: undefined
//         }
//     ]
// }

API

treeShortcut(tree, shortcutTriggerProp, shortcutTargetProp, shortcutName)

tree

Type: Anything

If it is indeed a tree (i.e. an array or plain object), it will be copied and modified with the shortcut. Otherwise, it will be returned unchanged.

shortcutTriggerProp

Type: string

The name of the prop which will trigger the shortcut.

shortcutTargetProp

Type: string

The name of the child prop which will be used as target of the shortcut.

shortcutName

Type: string

The name of the new prop to replace the shortcutTriggerProp in the parent object where the shortcut was triggered.

Detailed algorithm description

The treeShortcut(tree, shortcutTriggerProp, shortcutTargetProp, shortcutName) will do the following:

  1. If tree is an array, shallow-clone it and recurse on each element. Otherwise:

  2. If tree is not a plain object, just return the input (tree) unchanged. Otherwise:

  3. If tree does not have a key named shortcutTriggerProp, shallow-clone it and recurse on each key-value pair. Otherwise:

  4. Shallow-clone the tree object into tree_clone;

  5. If tree_clone has a key named shortcutName, delete it;

  6. For each (shallow) property in tree_clone:

    • If its name is shortcutTriggerProp, rename it to shortcutName and then:

      a. If its value is a plain object, replace it with value[shortcutTargetProp]. Otherwise:

      b. If its value is an array, recurse on its elements running steps a, b and c. Otherwise:

      c. If its value is neither an array nor a plain object, replace it with undefined.

      • Example: { a: 1 } becomes value[shortcutTargetProp];
      • Example: [{ a: 1 }, { a: 2 }] becomes [value[0][shortcutTargetProp], value[1][shortcutTargetProp]];
      • Example: [{ a: 1 }, 2] becomes [value[0][shortcutTargetProp], undefined];
      • Example: [null, undefined, new Date()] becomes [undefined, undefined, undefined];
    • Otherwise, recurse (i.e. call treeShortcut) on the value of the property;

  7. Return tree_clone.

TypeScript support

This module supports TypeScript by default. The return type of the treeShortcut method is properly constructed.

The tested versions are TS 4.1, 4.2, 4.3, 4.4 and 4.5.

Note: the new shortcut property will be set to readonly if (and only if) the inner property was readonly. If the inner property was deep into an array, the new shortcut property will be set to readonly if (and only if) the inner property was readonly on all leaves of that array.

Example:

import treeShortcut = require('tree-shortcut');

const tree = {
    items: [
        {
            foo: { bar: [1, 2, 3] },
        },
        {
            foo: { bar: [4, 5], baz: true },
        },
        {
            foo: { baz: false },
        },
        {
            foo: null,
        },
    ],
};

const newTree = treeShortcut(tree, 'foo', 'bar', 'foobar');
type NewTreeType = typeof newTree;
//=> {
//     items: Array<{ foobar: number[] | undefined }>;
// }

const tree2 = {
    items: [
        {
            foo: { bar: [1, 2, 3] },
        },
        {
            foo: { bar: [4, 5], baz: true },
        },
        {
            foo: { baz: false },
        },
        {
            foo: null,
        },
    ],
} as const;

const newTree2 = treeShortcut(tree2, 'foo', 'bar', 'foobar');
type NewTree2Type = typeof newTree2;
//=> {
//     readonly items: readonly [{
//         readonly foobar: readonly [1, 2, 3];
//     }, {
//         readonly foobar: readonly [4, 5];
//     }, {
//         foobar: undefined;
//     }, {
//         foobar: undefined;
//     }];
// }

Related

  • direct-deep-map: Deep map values in a tree directly on the desired places, with strong TypeScript support. Original tree is unchanged.

License

MIT © Pedro Augusto de Paula Barbosa