{"_id":"@borela-tech/ts-toolbox","_rev":"5-370f3131d6ec6863ac8370b4e8f583dd","name":"@borela-tech/ts-toolbox","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@borela-tech/ts-toolbox","version":"1.0.0","keywords":["borela","borela-tech","tech","typescript","utilities"],"author":{"name":"Alexandre Borela","email":"alexandre@borela.tech"},"license":"Apache-2.0","_id":"@borela-tech/ts-toolbox@1.0.0","maintainers":[{"name":"borela","email":"alexandre.borela@gmail.com"}],"homepage":"https://github.com/borela-tech/eslint-config#readme","bugs":{"url":"https://github.com/borela-tech/eslint-config/issues"},"dist":{"shasum":"f06143db767a07c8d123febb679ff29d932dda82","tarball":"https://registry.npmjs.org/@borela-tech/ts-toolbox/-/ts-toolbox-1.0.0.tgz","fileCount":72,"integrity":"sha512-QRbIXx6/pkVIZjdvfwkH7g4zOObfw4rgGabeMDrBs2Ug7eEVQTWOj8q75WVPJ2kt+ph33RN5Rp411YrLnEy+vg==","signatures":[{"sig":"MEQCIAqJuO+s0r5dLLOklJg3O6qIMQmEQRThVCezL3te915XAiAHfT7zeQJaoZ+irDYZzhGrc6K/zJX5lHXr6QixzZNQNQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":77942},"exports":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"gitHead":"dbe89ac5dcb9b17c8a935c17ec1ed74e8edfd637","scripts":{"lint":"./bin/lint","test":"./bin/test","build":"./bin/build","typecheck":"./bin/typecheck"},"_npmUser":{"name":"borela","email":"alexandre.borela@gmail.com"},"repository":{"url":"git+https://github.com/borela-tech/eslint-config.git","type":"git"},"_npmVersion":"11.11.0","description":"Shared TypeScript utilities for Borela Tech projects.","directories":{},"_nodeVersion":"25.8.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","jiti":"^2.6.1","vite":"^8.0.2","eslint":"^9.24.0","@swc/jest":"^0.2.39","typescript":"^5.0.0","@types/jest":"^30.0.0","@types/node":"^20.0.0","@microsoft/api-extractor":"^7.58.5","@borela-tech/eslint-config":"^2.3.0"},"peerDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/ts-toolbox_1.0.0_1780163610829_0.8250064705543494","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@borela-tech/ts-toolbox","version":"1.0.1","keywords":["borela","borela-tech","tech","typescript","utilities"],"author":{"name":"Alexandre Borela","email":"alexandre@borela.tech"},"license":"Apache-2.0","_id":"@borela-tech/ts-toolbox@1.0.1","maintainers":[{"name":"borela","email":"alexandre.borela@gmail.com"}],"homepage":"https://github.com/borela-tech/ts-toolbox#readme","bugs":{"url":"https://github.com/borela-tech/ts-toolbox/issues"},"dist":{"shasum":"af5444469b35c26b41794984ceb699760b2d53ce","tarball":"https://registry.npmjs.org/@borela-tech/ts-toolbox/-/ts-toolbox-1.0.1.tgz","fileCount":11,"integrity":"sha512-BHs4Ew6BvWUV32zZElHCtgjDzjCpXnNPF2y9KT5aIg/4PAHbeYwcDepMJLN71/vElX967KyTX+ftoICjbqjO1A==","signatures":[{"sig":"MEUCIQD8Awa7EPOlXwzSs3DZGIVci9NwhPvLhrRq92KkMJzt2gIgM+Jdn/NzmIrHE1kGikL/BuNS16SOOWcfzympaOgIlMg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74690},"exports":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"gitHead":"350c967b3301f56cc9cbb844ad660501a63cdc40","scripts":{"lint":"./bin/lint","test":"./bin/test","build":"./bin/build","typecheck":"./bin/typecheck"},"_npmUser":{"name":"borela","email":"alexandre.borela@gmail.com"},"repository":{"url":"git+https://github.com/borela-tech/ts-toolbox.git","type":"git"},"_npmVersion":"11.11.0","description":"Shared TypeScript utilities for Borela Tech projects.","directories":{},"_nodeVersion":"25.8.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","jiti":"^2.6.1","vite":"^8.0.2","eslint":"^9.24.0","@swc/jest":"^0.2.39","typescript":"^5.0.0","@types/jest":"^30.0.0","@types/node":"^20.0.0","@microsoft/api-extractor":"^7.58.5","@borela-tech/eslint-config":"^2.3.0"},"peerDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/ts-toolbox_1.0.1_1780166760483_0.7652692569133535","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@borela-tech/ts-toolbox","version":"1.0.2","keywords":["borela","borela-tech","tech","typescript","utilities"],"author":{"name":"Alexandre Borela","email":"alexandre@borela.tech"},"license":"Apache-2.0","_id":"@borela-tech/ts-toolbox@1.0.2","maintainers":[{"name":"borela","email":"alexandre.borela@gmail.com"}],"homepage":"https://github.com/borela-tech/ts-toolbox#readme","bugs":{"url":"https://github.com/borela-tech/ts-toolbox/issues"},"dist":{"shasum":"50cb82bfbbcf2207c0c89a4ba09b723e76013d34","tarball":"https://registry.npmjs.org/@borela-tech/ts-toolbox/-/ts-toolbox-1.0.2.tgz","fileCount":11,"integrity":"sha512-7Zy3LBvQhHEkC2JA/fL4fFln6x9jl+uLTR9fmpOVakm3IW/gHlekzcjmuiTjCqgZmiNy9dUrIL2aPGxLelA0fw==","signatures":[{"sig":"MEUCIQD9mC8nTVzOPx4apfzefP9tZy3vwWFDloSnanYUyC5PKAIgObsqozjyDzLxAx+C4NCtb5jACL9Az78XzmQppivy0xM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75263},"exports":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"gitHead":"10246eefe5732868a93eae45fee7cceeae1dc53d","scripts":{"lint":"./bin/lint","test":"./bin/test","build":"./bin/build","typecheck":"./bin/typecheck"},"_npmUser":{"name":"borela","email":"alexandre.borela@gmail.com"},"repository":{"url":"git+https://github.com/borela-tech/ts-toolbox.git","type":"git"},"_npmVersion":"11.11.0","description":"Shared TypeScript utilities for Borela Tech projects.","directories":{},"_nodeVersion":"25.8.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","jiti":"^2.6.1","vite":"^8.0.2","eslint":"^9.24.0","@swc/jest":"^0.2.39","typescript":"^5.0.0","@types/jest":"^30.0.0","@types/node":"^20.0.0","@microsoft/api-extractor":"^7.58.5","@borela-tech/eslint-config":"^3.0.1"},"peerDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/ts-toolbox_1.0.2_1782574095440_0.8429534820934448","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@borela-tech/ts-toolbox","version":"1.1.0","keywords":["borela","borela-tech","tech","typescript","utilities"],"author":{"name":"Alexandre Borela","email":"alexandre@borela.tech"},"license":"Apache-2.0","_id":"@borela-tech/ts-toolbox@1.1.0","maintainers":[{"name":"borela","email":"alexandre.borela@gmail.com"}],"homepage":"https://github.com/borela-tech/ts-toolbox#readme","bugs":{"url":"https://github.com/borela-tech/ts-toolbox/issues"},"dist":{"shasum":"310dac4907abc814830f73f171a580f87f728018","tarball":"https://registry.npmjs.org/@borela-tech/ts-toolbox/-/ts-toolbox-1.1.0.tgz","fileCount":11,"integrity":"sha512-7+PLhtqpG22r2DH/wCsWJ1aYtNRocFAbhicihZYHmyaA+DM3rSZUuulLHu5rAwCoHlp8V9xVwG1LSChE3PuRBA==","signatures":[{"sig":"MEYCIQDSvbt3Mf6aBPfhOzDDJrgB8hu/1oN3dpsRm3Tb2NK/YgIhAISyB/W8s9jTVr8TOvo4G6RhV+zdMiL5EBG6Pmdd2CYg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82019},"exports":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"gitHead":"272a069a4e709f3d36ffe3feb48e1086df842913","scripts":{"lint":"./bin/lint","test":"./bin/test","build":"./bin/build","typecheck":"./bin/typecheck"},"_npmUser":{"name":"borela","email":"alexandre.borela@gmail.com"},"repository":{"url":"git+https://github.com/borela-tech/ts-toolbox.git","type":"git"},"_npmVersion":"11.11.0","description":"Shared TypeScript utilities for Borela Tech projects.","directories":{},"_nodeVersion":"25.8.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","jiti":"^2.6.1","vite":"^8.0.2","eslint":"^9.24.0","@swc/jest":"^0.2.39","typescript":"^5.0.0","@types/jest":"^30.0.0","@types/node":"^20.0.0","@microsoft/api-extractor":"^7.58.5","@borela-tech/eslint-config":"^3.0.1"},"peerDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/ts-toolbox_1.1.0_1784989804690_0.7942119027028534","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@borela-tech/ts-toolbox","version":"1.2.0","description":"Shared TypeScript utilities for Borela Tech projects.","scripts":{"build":"./bin/build","lint":"./bin/lint","test":"./bin/test","typecheck":"./bin/typecheck"},"exports":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"repository":{"type":"git","url":"git+https://github.com/borela-tech/ts-toolbox.git"},"keywords":["borela","borela-tech","tech","typescript","utilities"],"author":{"name":"Alexandre Borela","email":"alexandre@borela.tech"},"license":"Apache-2.0","devDependencies":{"@borela-tech/eslint-config":"^3.0.1","@microsoft/api-extractor":"^7.58.5","@swc/jest":"^0.2.39","@types/jest":"^30.0.0","@types/node":"^20.0.0","eslint":"^9.24.0","jest":"^30.3.0","jiti":"^2.6.1","typescript":"^5.0.0","vite":"^8.0.2"},"peerDependencies":{"typescript":"~5.9.3"},"gitHead":"8be213c88bf8080f070f2ee87d154a3910afe310","_id":"@borela-tech/ts-toolbox@1.2.0","bugs":{"url":"https://github.com/borela-tech/ts-toolbox/issues"},"homepage":"https://github.com/borela-tech/ts-toolbox#readme","_nodeVersion":"25.8.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-c1kKpW/5ZDAqGvv8Hyb2vFlj8qEOAdEv7FX5Urcr9oXLmOTt52Bxl9Phf97oon+LGLdhG9ScufxGldD/J21n+w==","shasum":"d909d5afad0a6d9339ebaf3e009e61f989c9e810","tarball":"https://registry.npmjs.org/@borela-tech/ts-toolbox/-/ts-toolbox-1.2.0.tgz","fileCount":11,"unpackedSize":91133,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBQGdOeKmpwpSGqAp0NXr/D2CfIgg56nEI3BKSlKdV6JAiAMXabo+HJyHdTezk9q09HB34U97ITd+7JY2igYCFmc9A=="}]},"_npmUser":{"name":"borela","email":"alexandre.borela@gmail.com"},"directories":{},"maintainers":[{"name":"borela","email":"alexandre.borela@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ts-toolbox_1.2.0_1787408094498_0.6895378245280892"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-30T17:53:30.663Z","modified":"2026-08-22T14:14:54.822Z","1.0.0":"2026-05-30T17:53:30.964Z","1.0.1":"2026-05-30T18:46:00.615Z","1.0.2":"2026-06-27T15:28:15.606Z","1.1.0":"2026-07-25T14:30:04.833Z","1.2.0":"2026-08-22T14:14:54.640Z"},"bugs":{"url":"https://github.com/borela-tech/ts-toolbox/issues"},"author":{"name":"Alexandre Borela","email":"alexandre@borela.tech"},"license":"Apache-2.0","homepage":"https://github.com/borela-tech/ts-toolbox#readme","keywords":["borela","borela-tech","tech","typescript","utilities"],"repository":{"type":"git","url":"git+https://github.com/borela-tech/ts-toolbox.git"},"description":"Shared TypeScript utilities for Borela Tech projects.","maintainers":[{"name":"borela","email":"alexandre.borela@gmail.com"}],"readme":"# @borela-tech/ts-toolbox\n\n[![CI](https://github.com/borela-tech/ts-toolbox/actions/workflows/ci.yml/badge.svg)](https://github.com/borela-tech/ts-toolbox/actions/workflows/ci.yml)\n[![npm version](https://badge.fury.io/js/@borela-tech%2Fts-toolbox.svg)](https://badge.fury.io/js/@borela-tech%2Fts-toolbox)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n![Node Version](https://img.shields.io/badge/node-v25.8.1-brightgreen)\n\nShared TypeScript utilities for Borela Tech projects.\n\nA lightweight, **zero-runtime-dependency** collection of runtime functions and type-level utilities.\n\n- [Install](#install)\n- [Runtime API](#runtime-api)\n  - [`capitalize`](#capitalize)\n  - [`clamp`](#clamp)\n  - [`clampAndSnap`](#clampandsnap)\n  - [`debounce`](#debounce)\n  - [`dedent`](#dedent)\n  - [`dedentAndStrip`](#dedentandstrip)\n  - [`deepFreeze`](#deepfreeze)\n  - [`firstLine`](#firstline)\n  - [`indent`](#indent)\n  - [`interpolate`](#interpolate)\n  - [`lastLine`](#lastline)\n  - [`getNearestParentPackageJson`](#getnearestparentpackagejson)\n  - [`snap`](#snap)\n  - [`withTimeout`](#withtimeout)\n- [Type Utilities](#type-utilities)\n  - [`AnyFunction`](#anyfunction)\n  - [`DebouncedCallResult`, `DebouncedFunction`, `DebouncedFunctionParameters`](#debouncedcallresult-t-debouncedfunctiont-debouncedfunctionparameterst)\n  - [`Equals`](#equalsx-y)\n  - [`IsAbstract`](#isabstractt)\n  - [`MaybePromise`](#maybepromiset)\n  - [`NotNullable`, `NotNullish`, `NotUndefinable`, `Nullish`](#notnullablet-notnullisht-notundefinablet-nullisht)\n- [License](#license)\n\n## Install\n\n```sh\nnpm install @borela-tech/ts-toolbox\n```\n\nRequires **TypeScript ~5.9.3** as a peer dependency.\n\n## Runtime API\n\n### `capitalize`\n\nCapitalize the first letter of a string or template literal. When used as a\ntemplate tag, the first line (after the opening `` ` ``) and last line (before\nthe closing `` ` ``) are stripped.\n\n```ts\nimport {capitalize} from '@borela-tech/ts-toolbox'\n\ncapitalize('hello') // => 'Hello'\n\n// Template tag: first/last lines from formatting are stripped:\ncapitalize`\n  hello world\n`\n// => 'Hello world'\n```\n\n### `clamp`\n\nRestrict a number to the inclusive range `[min, max]`.\n\n- `value`: the number to clamp.\n- `min`: inclusive lower bound.\n- `max`: inclusive upper bound.\n\nNon-finite values are coerced: `+Infinity → max`, `-Infinity → min`. `NaN` is\nreturned as-is.\n\n```ts\nimport {clamp} from '@borela-tech/ts-toolbox'\n\nclamp(5, 0, 10)     // => 5\nclamp(-5, 0, 10)    // => 0\nclamp(15, 0, 10)    // => 10\nclamp(NaN, 0, 10)   // => NaN\nclamp(Infinity, 0, 10)  // => 10\nclamp(-Infinity, 0, 10) // => 0\n```\n\n### `clampAndSnap`\n\nSnap a number to the nearest multiple of `step`, then clamp the result to the\ninclusive range `[min, max]`.\n\n- `value`: the number to snap and clamp.\n- `step`: the snapping step; `value` is rounded to the nearest multiple of it.\n- `min`: inclusive lower bound.\n- `max`: inclusive upper bound.\n\nNon-finite values are coerced: `+Infinity → max`, `-Infinity → min`. `NaN` is\nreturned as-is.\n\n```ts\nimport {clampAndSnap} from '@borela-tech/ts-toolbox'\n\nclampAndSnap(7, 10, 0, 25)    // => 10\nclampAndSnap(35, 10, 0, 25)   // => 25\nclampAndSnap(-5, 10, 0, 25)   // => 0\nclampAndSnap(NaN, 10, 0, 25)  // => NaN\n```\n\n### `debounce`\n\nCreate a debounced function. Each call cancels the previous pending call. The\ntarget function automatically receives an `AbortSignal` as the last argument,\nbut does not need to declare it if it is not used. Canceled calls resolve to \n`debouncedCallCancelled`.\n\n- `delay`: time in milliseconds to wait before invoking the target function.\n- `...args`: the arguments passed to the target function (minus any trailing\n  `AbortSignal`).\n\n```ts\nimport {\n  debounce, \n  debouncedCallCancelled,\n} from '@borela-tech/ts-toolbox'\n\nconst DELAY = 100\n\nconst fn = async (x: number) => x * 2\nconst debouncedFn = debounce(fn)\nconst a = debouncedFn(DELAY, 1) // Cancelled.\nconst b = await debouncedFn(DELAY, 2) // Executed.\n\nconsole.log(a === debouncedCallCancelled) // => true\nconsole.log(b) // => 4\n\nconst fnWithSignal = async (x: number, signal: AbortSignal) => {\n  if (signal.aborted)\n    return\n  return x * 2\n}\nconst debouncedFnWithSignal = debounce(fnWithSignal)\nconst c = debouncedFnWithSignal(DELAY, 3) // Cancelled.\nconst d = await debouncedFnWithSignal(DELAY, 4) // Executed.\n\nconsole.log(c === debouncedCallCancelled) // => true\nconsole.log(d) // => 8\n```\n\n### `dedent`\n\nRemove common leading whitespace from all lines. The first and last lines for \ntemplate literals are always stripped.\n\n```ts\nimport {dedent} from '@borela-tech/ts-toolbox'\n\ndedent`\n    hello\n      indented\n    world\n`\n// => 'hello\\n  indented\\nworld'\n\ndedent('    hello\\n      indented\\n    world') \n// => 'hello\\n  indented\\nworld'\n```\n\n### `dedentAndStrip`\n\nLike `dedent`, but also strips leading and trailing empty lines from the\ncontent itself (not just the template formatting lines).\n\n```ts\nimport {dedentAndStrip} from '@borela-tech/ts-toolbox'\n\n// The empty lines around hello/world are stripped:\ndedentAndStrip`\n\n    hello\n    world\n\n`\n// => 'hello\\nworld'\n```\n\n### `deepFreeze`\n\nRecursively freeze an object, making it deeply immutable. Uses a `WeakSet` for cycle detection.\n\n```ts\nimport {deepFreeze} from '@borela-tech/ts-toolbox'\n\nconst obj = deepFreeze({a: 1, b: {c: 2}})\nobj.a = 42 // TypeError (in strict mode)\nobj.b.c = 3 // TypeError (in strict mode)\n```\n\n### `firstLine`\n\nReturn the first line of a string.\n\n```ts\nimport {firstLine} from '@borela-tech/ts-toolbox'\n\nfirstLine('hello\\nworld\\nfoo') // => 'hello'\nfirstLine('hello') // => 'hello'\n```\n\n### `indent`\n\nAdd indentation to each line of a string. Works on both plain strings and template\nliterals. When used as a template tag, the first and last formatting lines are\nstripped.\n\n- `count`: number of times to repeat the indent unit (default `1`).\n- `indentUnit`: the string to repeat per level (default `'  '`).\n\n```ts\nimport {indent} from '@borela-tech/ts-toolbox'\n\n// Template tag mode: indent by 2 spaces (default):\nindent`hello\\nworld`\n// => '  hello\\n  world'\n\n// Template tag with custom count and unit:\nindent(1, '\\t')`hello\\nworld`\n// => '\\thello\\n\\tworld'\n\n// Plain string mode:\nindent('hello\\nworld', 1, '  ')\n// => '  hello\\n  world'\n```\n\n### `interpolate`\n\nTemplate literal tag that aligns continuation lines of multiline interpolated\nvalues to match the indentation of the interpolation site. Leading and trailing\nempty lines in the template literal are stripped.\n\n```ts\nimport {interpolate} from '@borela-tech/ts-toolbox'\n\n// The line after the opening backtick and the line before the closing backtick\n// are always stripped (they come from formatting the template across lines):\nconst value = 'Alice\\nBob'\ninterpolate`\n  hello ${value}!\n`\n// => '  hello Alice\\n  Bob!'\n\nconst code = 'fn() {\\n  return 1\\n}'\ninterpolate`\n  ${code}\n`\n// => '  fn() {\\n    return 1\\n  }'\n```\n\n### `lastLine`\n\nReturn the last line of a string.\n\n```ts\nimport {lastLine} from '@borela-tech/ts-toolbox'\n\nlastLine('hello\\nworld\\nfoo') // => 'foo'\nlastLine('hello') // => 'hello'\n```\n\n### `getNearestParentPackageJson`\n\nWalk up the directory tree to find the nearest `package.json`.\n\n```ts\nimport {getNearestParentPackageJson} from '@borela-tech/ts-toolbox'\n\ngetNearestParentPackageJson('/home/user/projects/my-app/src')\n// => '/home/user/projects/my-app/package.json'\n// or undefined if not found\n```\n\n### `snap`\n\nRound a number to the nearest multiple of `step`. Rounds half up.\n\n- `value`: the number to round.\n- `step`: the multiple to round to; if `0`, `value` is returned as-is.\n\n```ts\nimport {snap} from '@borela-tech/ts-toolbox'\n\nsnap(7, 10)   // => 10\nsnap(3, 10)   // => 0\nsnap(15, 10)  // => 20\nsnap(25, 10)  // => 30\nsnap(0.3, 0.25) // => 0.25\n```\n\n### `withTimeout`\n\nCreate a time-limited version of a function. The target function automatically\nreceives an `AbortSignal` as the last argument, but does not need to declare it\nif it is not used. The signal is aborted after `timeoutMs`. Aborting is\ncooperative, not a forced kill: a long-running function keeps running, and if\nit never settles the returned promise stays pending.\n\nIf the target function settles before the timeout fires, the call resolves or\nrejects with the normal result or error. If the timeout fires first (or the\nfunction settles after it), the call resolves to `timedOutCallCancelled`,\nregardless of whether the function later resolves or rejects.\n\n- `timeoutMs`: time in milliseconds before the call is aborted.\n- `...args`: the arguments passed to the target function (minus any trailing\n  `AbortSignal`).\n\n```ts\nimport {\n  withTimeout,\n  timedOutCallCancelled,\n} from '@borela-tech/ts-toolbox'\n\nconst TIMEOUT = 100\n\nconst fn = async (x: number) => {\n  await new Promise((resolve) => setTimeout(resolve, 50))\n  return x * 2\n}\nconst abortableFn = withTimeout(fn)\nconst a = await abortableFn(TIMEOUT, 2) // Finishes in time.\nconst b = await abortableFn(10, 2) // Times out.\n\nconsole.log(a) // => 4\nconsole.log(b === timedOutCallCancelled) // => true\n\nconst fnWithSignal = async (x: number, signal: AbortSignal) => {\n  if (signal.aborted)\n    return\n  return x * 2\n}\nconst abortableFnWithSignal = withTimeout(fnWithSignal)\nconst c = await abortableFnWithSignal(TIMEOUT, 3)\nconst d = await abortableFnWithSignal(10, 4) // Aborted.\n\nconsole.log(c) // => 6\nconsole.log(d === timedOutCallCancelled) // => true\n```\n\n## Type Utilities\n\n### `AnyFunction`\n\nAny function signature.\n\n```ts\nimport type {AnyFunction} from '@borela-tech/ts-toolbox'\n\nfunction wrap<T extends AnyFunction>(fn: T) {\n  return (...args: Parameters<T>) => fn(...args)\n}\n```\n\n### `DebouncedCallResult<T>`, `DebouncedFunction<T>`, `DebouncedFunctionParameters<T>`\n\nTypes associated with the `debounce` runtime function.\n\n```ts\nimport type {\n  DebouncedCallResult,\n  DebouncedFunction,\n  DebouncedFunctionParameters,\n} from '@borela-tech/ts-toolbox'\n\ntype Fn = (x: number) => Promise<number>\n\ntype Params = DebouncedFunctionParameters<Fn> // [x: number]\ntype Debounced = DebouncedFunction<Fn>\n// (delay: number, ...args: [x: number]) => Promise<DebouncedCallResult<Fn>>\n\ntype Result = DebouncedCallResult<Fn>\n// number | typeof debouncedCallCancelled\n\n// If the function declares AbortSignal as its last param, it's stripped:\ntype FnWithSignal = (x: number, signal: AbortSignal) => Promise<number>\ntype StrippedParams = DebouncedFunctionParameters<FnWithSignal> // [x: number]\n```\n\n### `Equals<X, Y>`\n\nEvaluate to `true` when two types are structurally equal, `false` otherwise.\n\n```ts\nimport type {Equals} from '@borela-tech/ts-toolbox'\n\ntype A = Equals<{a: number}, {a: number}> // true\ntype B = Equals<{a: number}, {b: string}> // false\n```\n\n### `IsAbstract<T>`\n\nReturns `true` if `T` is an abstract constructor.\n\n```ts\nimport type {IsAbstract} from '@borela-tech/ts-toolbox'\n\nabstract class Animal {}\nclass Dog extends Animal {}\n\ntype A = IsAbstract<typeof Animal> // true\ntype B = IsAbstract<typeof Dog> // false\n```\n\n### `MaybePromise<T>`\n\nA type that may be synchronous or asynchronous.\n\n```ts\nimport type {MaybePromise} from '@borela-tech/ts-toolbox'\n\ntype A = MaybePromise<number> // number | PromiseLike<number>\n```\n\n### `NotNullable<T>`, `NotNullish<T>`, `NotUndefinable<T>`, `Nullish<T>`\n\nNull-handling utility types.\n\n```ts\nimport type {\n  NotNullable,\n  NotNullish,\n  NotUndefinable,\n  Nullish,\n} from '@borela-tech/ts-toolbox'\n\ntype A = NotNullable<string | null>       // string\ntype B = NotNullish<string | null | undefined> // string\ntype C = NotUndefinable<string | undefined>    // string\ntype D = Nullish<string>                 // string | null | undefined\n```\n\n## License\n\n[Apache-2.0](LICENSE.md)\n","readmeFilename":"README.md"}