min-heap-typed 1.49.8 → 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,22 +13,24 @@ import { IterableEntryBase } from '../base';
13
13
  * 3. Unique Keys: Keys are unique. If you try to insert another entry with the same key, the old entry will be replaced by the new one.
14
14
  * 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time.
15
15
  */
16
- export declare class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
16
+ export declare class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {
17
17
  protected _store: {
18
18
  [key: string]: HashMapStoreItem<K, V>;
19
19
  };
20
20
  protected _objMap: Map<object, V>;
21
21
  /**
22
- * The constructor function initializes a new instance of a class with optional entries and options.
23
- * @param entries - The `entries` parameter is an iterable containing key-value pairs `[K, V]`. It
24
- * is optional and defaults to an empty array `[]`. This parameter is used to initialize the map with
25
- * key-value pairs.
26
- * @param [options] - The `options` parameter is an optional object that can contain additional
27
- * configuration options for the constructor. In this case, it has one property:
22
+ * The constructor function initializes a HashMap object with an optional initial collection and
23
+ * options.
24
+ * @param rawCollection - The `rawCollection` parameter is an iterable collection of elements of type
25
+ * `T`. It is an optional parameter and its default value is an empty array `[]`.
26
+ * @param [options] - The `options` parameter is an optional object that can contain two properties:
28
27
  */
29
- constructor(entries?: Iterable<[K, V]>, options?: HashMapOptions<K>);
28
+ constructor(rawCollection?: Iterable<R>, options?: HashMapOptions<K, V, R>);
29
+ protected _toEntryFn: (rawElement: R) => [K, V];
30
+ get toEntryFn(): (rawElement: R) => [K, V];
30
31
  protected _size: number;
31
32
  get size(): number;
33
+ isEntry(rawElement: any): rawElement is [K, V];
32
34
  isEmpty(): boolean;
33
35
  clear(): void;
34
36
  /**
@@ -42,11 +44,13 @@ export declare class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
42
44
  */
43
45
  set(key: K, value: V): boolean;
44
46
  /**
45
- * The function "setMany" sets multiple key-value pairs in a map.
46
- * @param entries - The `entries` parameter is an iterable containing key-value pairs. Each
47
- * key-value pair is represented as an array with two entries: the key and the value.
47
+ * The function `setMany` takes an iterable collection of objects, maps each object to a key-value
48
+ * pair using a mapping function, and sets each key-value pair in the current object.
49
+ * @param rawCollection - The `rawCollection` parameter is an iterable collection of elements of type
50
+ * `T`.
51
+ * @returns The `setMany` function is returning an array of booleans.
48
52
  */
49
- setMany(entries: Iterable<[K, V]>): boolean[];
53
+ setMany(rawCollection: Iterable<R>): boolean[];
50
54
  /**
51
55
  * The `get` function retrieves a value from a map based on a given key, either from an object map or
52
56
  * a string map.
@@ -11,32 +11,49 @@ const utils_1 = require("../../utils");
11
11
  */
12
12
  class HashMap extends base_1.IterableEntryBase {
13
13
  /**
14
- * The constructor function initializes a new instance of a class with optional entries and options.
15
- * @param entries - The `entries` parameter is an iterable containing key-value pairs `[K, V]`. It
16
- * is optional and defaults to an empty array `[]`. This parameter is used to initialize the map with
17
- * key-value pairs.
18
- * @param [options] - The `options` parameter is an optional object that can contain additional
19
- * configuration options for the constructor. In this case, it has one property:
14
+ * The constructor function initializes a HashMap object with an optional initial collection and
15
+ * options.
16
+ * @param rawCollection - The `rawCollection` parameter is an iterable collection of elements of type
17
+ * `T`. It is an optional parameter and its default value is an empty array `[]`.
18
+ * @param [options] - The `options` parameter is an optional object that can contain two properties:
20
19
  */
21
- constructor(entries = [], options) {
20
+ constructor(rawCollection = [], options) {
22
21
  super();
23
22
  this._store = {};
24
23
  this._objMap = new Map();
24
+ this._toEntryFn = (rawElement) => {
25
+ if (this.isEntry(rawElement)) {
26
+ // TODO, For performance optimization, it may be necessary to only inspect the first element traversed.
27
+ return rawElement;
28
+ }
29
+ else {
30
+ throw new Error("If the provided rawCollection does not adhere to the [key, value] type format, the toEntryFn in the constructor's options parameter needs to specified.");
31
+ }
32
+ };
25
33
  this._size = 0;
26
34
  this._hashFn = (key) => String(key);
27
35
  if (options) {
28
- const { hashFn } = options;
36
+ const { hashFn, toEntryFn } = options;
29
37
  if (hashFn) {
30
38
  this._hashFn = hashFn;
31
39
  }
40
+ if (toEntryFn) {
41
+ this._toEntryFn = toEntryFn;
42
+ }
32
43
  }
33
- if (entries) {
34
- this.setMany(entries);
44
+ if (rawCollection) {
45
+ this.setMany(rawCollection);
35
46
  }
36
47
  }
48
+ get toEntryFn() {
49
+ return this._toEntryFn;
50
+ }
37
51
  get size() {
38
52
  return this._size;
39
53
  }
54
+ isEntry(rawElement) {
55
+ return Array.isArray(rawElement) && rawElement.length === 2;
56
+ }
40
57
  isEmpty() {
41
58
  return this.size === 0;
42
59
  }
@@ -71,14 +88,18 @@ class HashMap extends base_1.IterableEntryBase {
71
88
  return true;
72
89
  }
73
90
  /**
74
- * The function "setMany" sets multiple key-value pairs in a map.
75
- * @param entries - The `entries` parameter is an iterable containing key-value pairs. Each
76
- * key-value pair is represented as an array with two entries: the key and the value.
91
+ * The function `setMany` takes an iterable collection of objects, maps each object to a key-value
92
+ * pair using a mapping function, and sets each key-value pair in the current object.
93
+ * @param rawCollection - The `rawCollection` parameter is an iterable collection of elements of type
94
+ * `T`.
95
+ * @returns The `setMany` function is returning an array of booleans.
77
96
  */
78
- setMany(entries) {
97
+ setMany(rawCollection) {
79
98
  const results = [];
80
- for (const [key, value] of entries)
99
+ for (const rawEle of rawCollection) {
100
+ const [key, value] = this.toEntryFn(rawEle);
81
101
  results.push(this.set(key, value));
102
+ }
82
103
  return results;
83
104
  }
84
105
  /**
@@ -8,8 +8,9 @@ export type LinkedHashMapOptions<K> = {
8
8
  hashFn?: (key: K) => string;
9
9
  objHashFn?: (key: K) => object;
10
10
  };
11
- export type HashMapOptions<K> = {
11
+ export type HashMapOptions<K, V, T> = {
12
12
  hashFn?: (key: K) => string;
13
+ toEntryFn?: (rawElement: T) => [K, V];
13
14
  };
14
15
  export type HashMapStoreItem<K, V> = {
15
16
  key: K;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "min-heap-typed",
3
- "version": "1.49.8",
3
+ "version": "1.50.0",
4
4
  "description": "Min Heap. Javascript & Typescript Data Structure.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -132,6 +132,6 @@
132
132
  "typescript": "^4.9.5"
133
133
  },
134
134
  "dependencies": {
135
- "data-structure-typed": "^1.49.8"
135
+ "data-structure-typed": "^1.50.0"
136
136
  }
137
137
  }
@@ -98,16 +98,6 @@ export class AVLTree<
98
98
  return keyOrNodeOrEntry instanceof AVLTreeNode;
99
99
  }
100
100
 
101
- /**
102
- * The function "isNotNodeInstance" checks if a potential key is a K.
103
- * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
104
- * data type.
105
- * @returns a boolean value indicating whether the potentialKey is of type number or not.
106
- */
107
- override isNotNodeInstance(potentialKey: KeyOrNodeOrEntry<K, V, N>): potentialKey is K {
108
- return !(potentialKey instanceof AVLTreeNode);
109
- }
110
-
111
101
  /**
112
102
  * Time Complexity: O(log n)
113
103
  * Space Complexity: O(1)
@@ -196,7 +196,7 @@ export class BinaryTree<
196
196
  }
197
197
  } else if (this.isNode(keyOrNodeOrEntry)) {
198
198
  node = keyOrNodeOrEntry;
199
- } else if (this.isNotNodeInstance(keyOrNodeOrEntry)) {
199
+ } else if (!this.isNode(keyOrNodeOrEntry)) {
200
200
  node = this.createNode(keyOrNodeOrEntry, value);
201
201
  } else {
202
202
  return;
@@ -292,16 +292,6 @@ export class BinaryTree<
292
292
  return this.isRealNode(node) || node === null;
293
293
  }
294
294
 
295
- /**
296
- * The function "isNotNodeInstance" checks if a potential key is a K.
297
- * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
298
- * data type.
299
- * @returns a boolean value indicating whether the potentialKey is of type number or not.
300
- */
301
- isNotNodeInstance(potentialKey: KeyOrNodeOrEntry<K, V, N>): potentialKey is K {
302
- return !(potentialKey instanceof BinaryTreeNode);
303
- }
304
-
305
295
  /**
306
296
  * Time Complexity O(log n) - O(n)
307
297
  * Space Complexity O(1)
@@ -1028,7 +1018,7 @@ export class BinaryTree<
1028
1018
  *
1029
1019
  * The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree
1030
1020
  * structure, with the option to reverse the order of the nodes.
1031
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1021
+ * @param {K | N | null | undefined} beginNode - The `beginRoot` parameter represents the
1032
1022
  * starting node from which you want to find the path to the root. It can be of type `K`, `N`,
1033
1023
  * `null`, or `undefined`.
1034
1024
  * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
@@ -1036,20 +1026,20 @@ export class BinaryTree<
1036
1026
  * reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is
1037
1027
  * @returns The function `getPathToRoot` returns an array of nodes (`N[]`).
1038
1028
  */
1039
- getPathToRoot(beginRoot: KeyOrNodeOrEntry<K, V, N>, isReverse = true): N[] {
1029
+ getPathToRoot(beginNode: KeyOrNodeOrEntry<K, V, N>, isReverse = true): N[] {
1040
1030
  // TODO to support get path through passing key
1041
1031
  const result: N[] = [];
1042
- beginRoot = this.ensureNode(beginRoot);
1032
+ beginNode = this.ensureNode(beginNode);
1043
1033
 
1044
- if (!beginRoot) return result;
1034
+ if (!beginNode) return result;
1045
1035
 
1046
- while (beginRoot.parent) {
1036
+ while (beginNode.parent) {
1047
1037
  // Array.push + Array.reverse is more efficient than Array.unshift
1048
1038
  // TODO may consider using Deque, so far this is not the performance bottleneck
1049
- result.push(beginRoot);
1050
- beginRoot = beginRoot.parent;
1039
+ result.push(beginNode);
1040
+ beginNode = beginNode.parent;
1051
1041
  }
1052
- result.push(beginRoot);
1042
+ result.push(beginNode);
1053
1043
  return isReverse ? result.reverse() : result;
1054
1044
  }
1055
1045
 
@@ -1202,99 +1192,94 @@ export class BinaryTree<
1202
1192
  }
1203
1193
  }
1204
1194
 
1205
- /**
1206
- * Time complexity: O(n)
1207
- * Space complexity: O(log n)
1208
- */
1209
-
1210
- subTreeTraverse<C extends BTNCallback<N>>(
1211
- callback?: C,
1212
- beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1213
- iterationType?: IterationType,
1214
- includeNull?: false
1215
- ): ReturnType<C>[];
1216
-
1217
- subTreeTraverse<C extends BTNCallback<N>>(
1218
- callback?: C,
1219
- beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1220
- iterationType?: IterationType,
1221
- includeNull?: undefined
1222
- ): ReturnType<C>[];
1223
-
1224
- subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1225
- callback?: C,
1226
- beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1227
- iterationType?: IterationType,
1228
- includeNull?: true
1229
- ): ReturnType<C>[];
1230
-
1231
- /**
1232
- * Time complexity: O(n)
1233
- * Space complexity: O(log n)
1234
- *
1235
- * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each
1236
- * node, either recursively or iteratively.
1237
- * @param {C} callback - The `callback` parameter is a function that will be called for each node in
1238
- * the subtree traversal. It takes a single parameter, which is the current node being traversed, and
1239
- * returns a value of any type.
1240
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1241
- * starting node or key from which the subtree traversal should begin. It can be of type `K`,
1242
- * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
1243
- * the default value.
1244
- * @param iterationType - The `iterationType` parameter determines the type of traversal to be
1245
- * performed on the subtree. It can have two possible values:
1246
- * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
1247
- * whether to include null values in the traversal. If `includeNull` is set to `true`, the
1248
- * traversal will include null values, otherwise it will skip them.
1249
- * @returns The function `subTreeTraverse` returns an array of values that are the result of invoking
1250
- * the `callback` function on each node in the subtree. The type of the array nodes is determined
1251
- * by the return type of the `callback` function.
1252
- */
1253
- subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1254
- callback: C = this._defaultOneParamCallback as C,
1255
- beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
1256
- iterationType = this.iterationType,
1257
- includeNull = false
1258
- ): ReturnType<C>[] {
1259
- beginRoot = this.ensureNode(beginRoot);
1260
-
1261
- const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
1262
- if (!beginRoot) return ans;
1263
-
1264
- if (iterationType === IterationType.RECURSIVE) {
1265
- const _traverse = (cur: N | null | undefined) => {
1266
- if (cur !== undefined) {
1267
- ans.push(callback(cur));
1268
- if (includeNull) {
1269
- cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
1270
- cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
1271
- } else {
1272
- cur && cur.left && _traverse(cur.left);
1273
- cur && cur.right && _traverse(cur.right);
1274
- }
1275
- }
1276
- };
1277
-
1278
- _traverse(beginRoot);
1279
- } else {
1280
- const stack: (N | null | undefined)[] = [beginRoot];
1281
-
1282
- while (stack.length > 0) {
1283
- const cur = stack.pop();
1284
- if (cur !== undefined) {
1285
- ans.push(callback(cur));
1286
- if (includeNull) {
1287
- cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
1288
- cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
1289
- } else {
1290
- cur && cur.right && stack.push(cur.right);
1291
- cur && cur.left && stack.push(cur.left);
1292
- }
1293
- }
1294
- }
1295
- }
1296
- return ans;
1297
- }
1195
+ // /**
1196
+ // * Time complexity: O(n)
1197
+ // * Space complexity: O(log n)
1198
+ // */
1199
+ //
1200
+ // subTreeTraverse<C extends BTNCallback<N>>(
1201
+ // callback?: C,
1202
+ // beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1203
+ // iterationType?: IterationType,
1204
+ // includeNull?: false
1205
+ // ): ReturnType<C>[];
1206
+ //
1207
+ // subTreeTraverse<C extends BTNCallback<N | null>>(
1208
+ // callback?: C,
1209
+ // beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1210
+ // iterationType?: IterationType,
1211
+ // includeNull?: true
1212
+ // ): ReturnType<C>[];
1213
+ //
1214
+ // /**
1215
+ // * Time complexity: O(n)
1216
+ // * Space complexity: O(log n)
1217
+ // *
1218
+ // * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each
1219
+ // * node, either recursively or iteratively.
1220
+ // * @param {C} callback - The `callback` parameter is a function that will be called for each node in
1221
+ // * the subtree traversal. It takes a single parameter, which is the current node being traversed, and
1222
+ // * returns a value of any type.
1223
+ // * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1224
+ // * starting node or key from which the subtree traversal should begin. It can be of type `K`,
1225
+ // * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
1226
+ // * the default value.
1227
+ // * @param iterationType - The `iterationType` parameter determines the type of traversal to be
1228
+ // * performed on the subtree. It can have two possible values:
1229
+ // * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
1230
+ // * whether to include null values in the traversal. If `includeNull` is set to `true`, the
1231
+ // * traversal will include null values, otherwise it will skip them.
1232
+ // * @returns The function `subTreeTraverse` returns an array of values that are the result of invoking
1233
+ // * the `callback` function on each node in the subtree. The type of the array nodes is determined
1234
+ // * by the return type of the `callback` function.
1235
+ // */
1236
+ // subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1237
+ // callback: C = this._defaultOneParamCallback as C,
1238
+ // beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
1239
+ // iterationType = this.iterationType,
1240
+ // includeNull = false
1241
+ // ): ReturnType<C>[] {
1242
+ // console.warn('subTreeTraverse is unnecessary, since the dfs method can substitute it.');
1243
+ //
1244
+ // beginRoot = this.ensureNode(beginRoot);
1245
+ //
1246
+ // const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
1247
+ // if (!beginRoot) return ans;
1248
+ //
1249
+ // if (iterationType === IterationType.RECURSIVE) {
1250
+ // const _traverse = (cur: N | null | undefined) => {
1251
+ // if (cur !== undefined) {
1252
+ // ans.push(callback(cur));
1253
+ // if (includeNull) {
1254
+ // cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
1255
+ // cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
1256
+ // } else {
1257
+ // cur && cur.left && _traverse(cur.left);
1258
+ // cur && cur.right && _traverse(cur.right);
1259
+ // }
1260
+ // }
1261
+ // };
1262
+ //
1263
+ // _traverse(beginRoot);
1264
+ // } else {
1265
+ // const stack: (N | null | undefined)[] = [beginRoot];
1266
+ //
1267
+ // while (stack.length > 0) {
1268
+ // const cur = stack.pop();
1269
+ // if (cur !== undefined) {
1270
+ // ans.push(callback(cur));
1271
+ // if (includeNull) {
1272
+ // cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
1273
+ // cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
1274
+ // } else {
1275
+ // cur && cur.right && stack.push(cur.right);
1276
+ // cur && cur.left && stack.push(cur.left);
1277
+ // }
1278
+ // }
1279
+ // }
1280
+ // }
1281
+ // return ans;
1282
+ // }
1298
1283
 
1299
1284
  dfs<C extends BTNCallback<N>>(
1300
1285
  callback?: C,
@@ -1304,15 +1289,7 @@ export class BinaryTree<
1304
1289
  includeNull?: false
1305
1290
  ): ReturnType<C>[];
1306
1291
 
1307
- dfs<C extends BTNCallback<N>>(
1308
- callback?: C,
1309
- pattern?: DFSOrderPattern,
1310
- beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1311
- iterationType?: IterationType,
1312
- includeNull?: undefined
1313
- ): ReturnType<C>[];
1314
-
1315
- dfs<C extends BTNCallback<N | null | undefined>>(
1292
+ dfs<C extends BTNCallback<N | null>>(
1316
1293
  callback?: C,
1317
1294
  pattern?: DFSOrderPattern,
1318
1295
  beginRoot?: KeyOrNodeOrEntry<K, V, N>,
@@ -1450,14 +1427,7 @@ export class BinaryTree<
1450
1427
  includeNull?: false
1451
1428
  ): ReturnType<C>[];
1452
1429
 
1453
- bfs<C extends BTNCallback<N>>(
1454
- callback?: C,
1455
- beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1456
- iterationType?: IterationType,
1457
- includeNull?: undefined
1458
- ): ReturnType<C>[];
1459
-
1460
- bfs<C extends BTNCallback<N | null | undefined>>(
1430
+ bfs<C extends BTNCallback<N | null>>(
1461
1431
  callback?: C,
1462
1432
  beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1463
1433
  iterationType?: IterationType,
@@ -1485,7 +1455,7 @@ export class BinaryTree<
1485
1455
  * @returns an array of values that are the result of invoking the callback function on each node in
1486
1456
  * the breadth-first traversal of a binary tree.
1487
1457
  */
1488
- bfs<C extends BTNCallback<N | null | undefined>>(
1458
+ bfs<C extends BTNCallback<N | null>>(
1489
1459
  callback: C = this._defaultOneParamCallback as C,
1490
1460
  beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
1491
1461
  iterationType = this.iterationType,
@@ -1551,14 +1521,7 @@ export class BinaryTree<
1551
1521
  includeNull?: false
1552
1522
  ): ReturnType<C>[][];
1553
1523
 
1554
- listLevels<C extends BTNCallback<N>>(
1555
- callback?: C,
1556
- beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1557
- iterationType?: IterationType,
1558
- includeNull?: undefined
1559
- ): ReturnType<C>[][];
1560
-
1561
- listLevels<C extends BTNCallback<N | null | undefined>>(
1524
+ listLevels<C extends BTNCallback<N | null>>(
1562
1525
  callback?: C,
1563
1526
  beginRoot?: KeyOrNodeOrEntry<K, V, N>,
1564
1527
  iterationType?: IterationType,
@@ -1586,7 +1549,7 @@ export class BinaryTree<
1586
1549
  * be excluded
1587
1550
  * @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
1588
1551
  */
1589
- listLevels<C extends BTNCallback<N | null | undefined>>(
1552
+ listLevels<C extends BTNCallback<N | null>>(
1590
1553
  callback: C = this._defaultOneParamCallback as C,
1591
1554
  beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
1592
1555
  iterationType = this.iterationType,
@@ -1597,7 +1560,7 @@ export class BinaryTree<
1597
1560
  if (!beginRoot) return levelsNodes;
1598
1561
 
1599
1562
  if (iterationType === IterationType.RECURSIVE) {
1600
- const _recursive = (node: N | null | undefined, level: number) => {
1563
+ const _recursive = (node: N | null, level: number) => {
1601
1564
  if (!levelsNodes[level]) levelsNodes[level] = [];
1602
1565
  levelsNodes[level].push(callback(node));
1603
1566
  if (includeNull) {
@@ -1611,7 +1574,7 @@ export class BinaryTree<
1611
1574
 
1612
1575
  _recursive(beginRoot, 0);
1613
1576
  } else {
1614
- const stack: [N | null | undefined, number][] = [[beginRoot, 0]];
1577
+ const stack: [N | null, number][] = [[beginRoot, 0]];
1615
1578
 
1616
1579
  while (stack.length > 0) {
1617
1580
  const head = stack.pop()!;