Transparent, Type-safe wrappers for your Typescript functions.
Install ts-wrappers
to use the wrapper
helper or copy and paste the utility wrappers to your project!
npm install ts-wrappers # Using npm
pnpm add ts-wrappers # Using pnpm
yarn add ts-wrappers # Using yarn
API | description |
---|---|
wrapper(cb) |
Utility helper for creating type-safe function wrappers |
als(storage, init)(fn) |
Execute a function within an AsyncLocalStorage context |
debounce(wait, leading)(fn) |
Debounce a function's invocation |
delay(wait)(fn) |
Delay a function's invocation |
intercept(otherFn)(fn) |
Intercept a function with another one |
memoize(hashFn, cache)(fn) |
Memoize a function based on its arguments |
once(fn) |
Invoke a function only once in a program lifecycle |
repeat(count)(fn) |
Repeat a function |
throttle(wait)(fn) |
Throttle a function's invocation |
trace(fn) |
Log a function's arguments and duration |
You can demo the pre-made common wrappers above by running the following:
npx tsx <name>.ts
NB: replace
<name>
with the name of the wrapper you would like to demo. e.g als, debounce etc.
Wrappers such as trace()
and once()
can be applied directly to functions without any other arguments.
E.g trace
import { trace } from "ts-wrappers";
function add(a: number, b: number) {
return a + b;
}
const tracedAdd = trace(add);
// ^? (a: number, b: number) => number
console.log(tracedAdd(4, 5));
console.log(tracedAdd(3, 5));
OUTPUT
add(4,5) | duration: 0.114ms
9
add(10,12) | duration: 0.005ms
22
Other wrappers such as retry()
, debounce()
, memoize()
, etc. require some external arguments that inform the behavior of the wrapper. These arguments are provided in a "curried" manner.
import { memoize } from "ts-wrappers";
let fib = function (n: number): number {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
};
// A simple hash function
const hashFn = (x: number) => x;
// Redefining is super important here so it is memoized for recursive calls
fib = memoize(hashFn)(fib);
// Applying trace to the function to see its performance
const tFib = trace(fib);
console.log(tFib(10));
console.log(tFib(10));
OUTPUT
fib(10) | duration: 0.369ms
55
-----
fib(10) | duration: 0.016ms
55
You can also define your type-safe wrappers using the basic examples inside of templates
directory.
You can copy and modify the code to suite your needs.
Heare are the available templates and what they allow you to do.
template | Type-safe | Transparent | Arguments? | Scopes |
---|---|---|---|---|
basic | ✅ | ✅ | 🚫 | 2 |
basic (with wrapper ) |
✅ | ✅ | 🚫 | 1 |
complex | ✅ | ✅ | ✅ | 3 |
complex (with wrapper ) |
✅ | ✅ | ✅ | 2 |
Key
- Type-safe: cannot apply a wrapper to function which does not match its expected args
- Transparent: correctly infers the wrapped function type (both arguments and return type) when applied
- Arguments?: whether or not the wrapper accepts extra arguments (other than the functions'), e.g
delay
in theretry()
wrapper - Scopes: how many levels of scope for defining variables. e.g the wrapper scope, wrapped function scope.
Manually defining wrappers using the templates has better performance than using the wrapper
helper. All common wrappers are defined manually for the best performance, however the wrapper
helper aims to provide an easier approach to dealing with types.
The source-code for the performance evaluation can be found in demos/benchmark.ts, and can be ran with
npx tsx demos/benchmark.ts
The following repositories were the seeds for, and helpful in building this out!