{"record":{"id":"f215fc391bb61461","repo":"TheAlgorithms/JavaScript","slug":"key-has-to-be-a-function-or-else-left-undefined","errorCode":null,"errorMessage":"key has to be a function or else left undefined","messagePattern":"key has to be a function or else left undefined","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Search/UnionFind.js","lineNumber":20,"sourceCode":" * union find data structure for javascript\n *\n * In computer science, a disjoint-set data structure, also called a union–find data structure or merge–find set,\n * is a data structure that stores a collection of disjoint (non-overlapping) sets. Equivalently, it stores a partition\n * of a set into disjoint subsets. It provides operations for adding new sets, merging sets (replacing them by their union),\n * and finding a representative member of a set.\n * The last operation allows to find out efficiently if any two elements are in the same or different sets.\n *\n * Disjoint-set data structures play a key role in Kruskal's algorithm for finding the minimum spanning tree of a graph.\n * The importance of minimum spanning trees means that disjoint-set data structures underlie a wide variety of algorithms.\n * In addition, disjoint-set data structures also have applications to symbolic computation, as well in compilers,\n * especially for register allocation problems.\n *\n * you can learn more on disjoint-set / union–find data structure at https://en.wikipedia.org/wiki/Disjoint-set_data_structure\n */\nfunction UnionFind(n, key) {\n  if (!(this instanceof UnionFind)) return new UnionFind(n)\n  if (key && typeof key !== 'function') {\n    throw new Error('key has to be a function or else left undefined')\n  }\n  let cnt, length\n  // init Union Find with number of distinct groups. Each group will be referred to as index of the array of size 'size' starting at 0.\n  // Provide an optional key function that maps these indices. I.e., for the groups starting with 1 provide function(a){return a-1;}. The default value is function(a){return a;}.\n  key =\n    key ||\n    function (a) {\n      return a\n    }\n  cnt = length = n\n  const id = new Array(n)\n  const sz = new Array(n)\n  for (let i = 0; i < n; i++) {\n    id[i] = i\n    sz[i] = 1\n  }\n  // Returns the number of elements of uf object.\n  this.size = function () {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/TheAlgorithms/JavaScript/blob/5c39e87a9a31f279c60f830ad74a845e4788a517/Search/UnionFind.js#L2-L38","documentation":"Thrown by the UnionFind constructor when an optional key argument is supplied but is not a function. The key is used internally to map caller indices to internal indices (key = key || function(a){return a}), so a non-function key would break every subsequent find/union call. Only undefined/omitted triggers the default; any other truthy non-function type is rejected.","triggerScenarios":"Calling new UnionFind(n, 'id'), new UnionFind(n, 5), new UnionFind(n, {map: fn}), or new UnionFind(n, true). Passing null does NOT throw (it is falsy, so the default function is used).","commonSituations":"Passing a key string instead of an accessor function; passing an object whose property is the function but forgetting to extract it; copy-paste from an API that expects a string mapper.","solutions":["Omit the second argument entirely to use the identity mapping.","Pass an actual function, e.g. new UnionFind(n, (a) => a - 1) for 1-based indices.","Pass null or undefined (not some other falsy placeholder) to take the default."],"exampleFix":"// before\nconst uf = new UnionFind(n, 'id')\n\n// after\nconst uf = new UnionFind(n, (a) => a - 1) // 1-based to 0-based mapping","handlingStrategy":"type-guard","validationCode":"function safeUnionFind(n, key) {\n  if (key !== undefined && typeof key !== 'function') {\n    throw new TypeError('key must be a function or undefined')\n  }\n  return new UnionFind(n, key)\n}","typeGuard":"function isOptionalFunction(k) {\n  return k === undefined || k === null || typeof k === 'function'\n}","tryCatchPattern":"try {\n  new UnionFind(n, key)\n} catch (e) {\n  if (e.message.includes('key has to be a function')) {\n    new UnionFind(n) // retry with default identity key\n  } else throw e\n}","preventionTips":["Omit the key argument when you want the identity mapping.","Pass null (falsy) rather than a placeholder object to take the default.","Wrap 1-based indices with a key function like (a) => a - 1."],"tags":["type-check","union-find","constructor","input-validation"],"backgroundTag":null,"analyzedSha":"5c39e87a9a31f279c60f830ad74a845e4788a517","analyzedAt":"2026-08-13T04:54:54.474Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}