npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

map-tree-utils

v1.0.10

Published

Tiny TypeScript utilities to convert between flat Map<string, T> structures and nested tree arrays

Readme

npm version Coverage

map-tree-utils

Tiny TypeScript utilities to convert between flat Map<string, T> structures and nested tree arrays.

Install

# npm
npm install map-tree-utils

# yarn
yarn add map-tree-utils

# pnpm
pnpm add map-tree-utils

# bun
bun i map-tree-utils

Why

When working with hierarchical data, you often face two common tasks:

  1. You receive a nested tree (e.g., from an API or authored JSON) and want to normalize it into a flat Map for fast lookups and updates.

  2. You have a flat structure (e.g., a Map keyed by id) and need to render it as a nested tree for UI or export.

map-tree-utils provides two small, focused helpers with zero runtime dependencies to handle this:

  • getTree — convert a Map<string, T> (flat) into a nested array of root nodes (tree).

  • getMap — convert a nested array (tree) into a Map<string, AnyObj> (flat).

Written in TypeScript, both functions are simple, predictable, and easy to drop into any frontend or backend project. They save you from writing repetitive boilerplate code while keeping your data handling fast and type-safe.

Quick example

import { getTree, getMap } from "map-tree-utils";

// --- Example: flat Map representing hierarchical data ---
const map = new Map([
  ["1", { id: "1", name: "Root" }],
  ["2", { id: "2", name: "Child A", parentId: "1" }],
  ["3", { id: "3", name: "Child B", parentId: "1" }],
  ["4", { id: "4", name: "Grandchild", parentId: "2" }],
]);

// Convert flat Map -> nested tree
const tree = getTree(map);
console.log("Nested tree:");
console.log(JSON.stringify(tree, null, 2));

// Convert back: nested tree -> flat Map
const flatMap = getMap(tree);
console.log("Flattened Map, item with id '4':");
console.log(flatMap.get("4")); 
// Output: { id: "4", name: "Grandchild", parentId: "2" }

// Get sorted tree: flat Map -> sorted tree
const stortedTree = getTree(map, "children", "parentId", "ord", "asc");
console.log("Sorted tree:");
console.log(JSON.stringify(stortedTree, null, 2));

React example

Minimal example

demo:
https://evgen002.github.io/map-tree-demo/

import { useMemo, useState } from "react";
import { getMap, getTree } from "map-tree-utils";

interface Tree {
  code: string;
  name: string;
  childs?: Tree[];
}

const tree: Tree[] = [
  {
    code: "1",
    name: "one",
    childs: [
      { code: "1_1", name: "child_one" },
      { code: "1_2", name: "child_two" },
    ],
  },
];

function App() {
  const [normalized, setNormalized] = useState(
    getMap(tree, "childs", "parentCode", "code")
  );

  const update = () => {
    setNormalized((prev) => {
      const map = new Map(prev);
      const prevTarget = map.get("1_2");

      if (prevTarget) {
        map.set("1_2", { ...prevTarget, name: "John" });

        return map;
      } else {
        return prev;
      }
    });
  };

  const updatedTree = useMemo(() => {
    return getTree(normalized, "childs", "parentCode");
  }, [normalized]);

  return (
    <div className="example">
      <h1>Map Tree Utils - DEMO</h1>
      <pre>{JSON.stringify(normalized.get("1_2"))}</pre>
      <TreeNode tree={updatedTree} />
      <button onClick={update}>update</button>
    </div>
  );
}

function TreeNode({ tree }: { tree: Tree[] }) {
  return (
    <ul>
      {tree.map((node) => (
        <li key={node.code}>
          {node.name}
          {node.childs && node.childs.length > 0 && (
            <TreeNode tree={node.childs} />
          )}
        </li>
      ))}
    </ul>
  );
}

export default App;

API

getTree<T>(map: Map<string, T>, childKey = "children", parentKey = "parentId"): Array<T & AnyObj>

Converts a Map of nodes into a nested array of root nodes.

Parameters

  • map: Map<string, T> - a Map where each value is a node object containing an identifier and optionally a parent reference.

  • childKey: string - the key to use for children arrays in the output nodes. Default: "children".

  • parentKey: string - the key used on nodes to identify their parent. Default: "parentId".

  • sortBy: string | (a, b) => number - used to return sorted tree

Returns

An array of nodes that are roots (nodes with no parent found in the provided Map). Each node in the returned tree is a shallow copy of the original node with an added children (or custom childKey) array.

Notes

  • The function creates shallow copies of nodes so the original Map values are not mutated.

  • If a node references a parentKey: string that does not exist in the Map, the node will be treated as a root.

getMap(tree: AnyObj[], childKey = "children", parentKey = "parentId", idKey = "id"): Map<string, AnyObj>

Flattens a nested tree array into a Map<string, AnyObj> keyed by id (or a custom idKey).

Parameters

  • tree: AnyObj[] - array of tree nodes (roots).

  • childKey: string - property name that holds child nodes. Default: "children".

  • parentKey: string - property name to be assigned to flattened nodes to indicate their parent id. Default: "parentId".

  • idKey: string - property name used in the original nodes to identify them. Default: "id".

Returns

A Map<string, AnyObj> where each key is the stringified id and each value is a shallow copy of the node (the children property is removed). Each child node will have a parentId pointing to its parent in the flattened structure.

Notes

The function will coerce the id value to String() when using it as a Map key.

children arrays are omitted in the flattened node objects.

Performance

Both utilities walk every node exactly once and perform O(N) operations (plus Map lookups which are O(1) amortized). They are suitable for reasonably sized trees used in frontend apps or typical backend data normalization tasks.

License: MIT