Simplify an object tree with a shortcut. TypeScript supported.
$ npm install tree-shortcut
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 beginsshortcutTargetProp
: The name of the nested property, target of the shortcutshortcutName
: The name of the new property that will replaceshortcutTriggerProp
, 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.
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
// }
// ]
// }
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.
Type: string
The name of the prop which will trigger the shortcut.
Type: string
The name of the child prop which will be used as target of the shortcut.
Type: string
The name of the new prop to replace the shortcutTriggerProp
in the parent object where the shortcut was triggered.
The treeShortcut(tree, shortcutTriggerProp, shortcutTargetProp, shortcutName)
will do the following:
-
If
tree
is an array, shallow-clone it and recurse on each element. Otherwise: -
If
tree
is not a plain object, just return the input (tree
) unchanged. Otherwise: -
If
tree
does not have a key namedshortcutTriggerProp
, shallow-clone it and recurse on each key-value pair. Otherwise: -
Shallow-clone the
tree
object intotree_clone
; -
If
tree_clone
has a key namedshortcutName
, delete it; -
For each (shallow) property in
tree_clone
:-
If its name is
shortcutTriggerProp
, rename it toshortcutName
and then:a. If its
value
is a plain object, replace it withvalue[shortcutTargetProp]
. Otherwise:b. If its
value
is an array, recurse on its elements running stepsa
,b
andc
. Otherwise:c. If its
value
is neither an array nor a plain object, replace it withundefined
.- Example:
{ a: 1 }
becomesvalue[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]
;
- Example:
-
Otherwise, recurse (i.e. call
treeShortcut
) on the value of the property;
-
-
Return
tree_clone
.
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;
// }];
// }
direct-deep-map
: Deep map values in a tree directly on the desired places, with strong TypeScript support. Original tree is unchanged.