Image inspired by trashh_dev's stream starting screen.
TypeScript Worker Threads Made Simple
A lightweight library for running TypeScript functions in worker threads with type safety and a simple API.
I created Twerker out of necessity. While there are several worker thread libraries available, none of them provided the perfect combination of simplicity, type-safety, and bare-minimum functionality that I was looking for. Most existing solutions were either over-engineered or lacked proper TypeScript support.
Twerker aims to do one thing and do it well: provide a straightforward, type-safe way to run CPU-intensive tasks in worker threads. No bells and whistles, no complex configurations - just a clean API that works out of the box.
- π Type Safe: Full TypeScript support with automatic type inference for worker functions
 - π Simple API: Run any function in a worker thread with minimal setup
 - π§΅ Thread Pools: Create worker pools for processing multiple tasks in parallel
 - π Asynchronous: Promise-based API for seamless integration
 - π§© Preserves Context: Your functions run with proper access to imports and dependencies
 - π Full Dependency Support: Access sibling functions and imported modules in your worker threads
 - π Clean Exit: Worker pools terminate properly when no longer needed
 
npm install twerkerimport run from 'twerker';
// Define a function to run in a worker thread
function expensiveCalculation(n: number): number {
  let result = 0;
  for (let i = 0; i < n; i++) {
    result += Math.sqrt(i);
  }
  return result;
}
async function main() {
  // Create a worker
  const worker = run(expensiveCalculation);
  
  // Execute the function in a worker thread
  const result = await worker.execute(1000000);
  console.log('Result:', result);
  
  // Create a worker pool with 4 workers
  const pool = worker.createPool({ numWorkers: 4 });
  
  // Queue multiple tasks
  const results = await Promise.all([
    pool.queue(1000000),
    pool.queue(2000000),
    pool.queue(3000000),
    pool.queue(4000000)
  ]);
  
  console.log('Results:', results);
  
  // Terminate the pool when done
  await pool.terminateWhenDone();
}
main().catch(console.error);Twerker automatically handles sibling functions and imported modules in your worker threads. This means you can:
- Call sibling functions: Use other functions defined in the same file as your worker function
 - Use imported modules: Access modules imported in your file
 - Handle both NodeJS built-ins and local modules: Works with the Node.js standard library and local project imports
 
Example with sibling functions and imports:
import crypto from 'crypto';
import { subtract } from './subtract';
// Sibling function
function add(a: number, b: number): number {
  return a + b;
}
// Worker function that uses sibling functions and imports
async function processData(name: string, delayMs: number): Promise<string> {
  // Use the 'add' sibling function
  const sum = subtract(add(delayMs, 500), 2);
  // Use the imported crypto module
  const id = crypto.randomUUID().slice(0, 8);
  return `Hello, ${name} (ID: ${id}, processed in ${sum}ms)`;
}
// Use with Twerker - sibling functions and imports work automatically
const worker = run(processData);
const result = await worker.execute('World', 100);Twerker analyzes your source code and:
- Detects imported modules and makes them available in the worker context
 - Captures sibling functions and includes them in the worker thread
 - Handles special cases like 
thisbinding for methods on imported modules - Ensures proper cleanup after execution
 
Creates a worker from a TypeScript function.
const worker = run(myFunction, { 
  resourceLimits: { maxOldGenerationSizeMb: 256 }
});The Worker object returned by the run function.
execute(...args): Execute the worker function with the provided argumentscreatePool(options): Create a worker pool for processing multiple tasksunref(): Unref the worker from the Node.js event loop (allows program to exit naturally)
A pool of workers for processing multiple tasks in parallel.
queue(...args): Queue a task to be processed by an available workerwaitForAllTasks(): Wait for all queued and running tasks to completeterminateWhenDone(): Terminate all workers after all tasks are completedterminate(): Terminate all workers immediately (cancels pending tasks)unref(): Unref the worker pool from the Node.js event loop
When working with worker threads, it's important to properly manage resources:
- Always call 
terminateWhenDone()when you're done with a worker pool - Use 
unref()when you want the program to exit naturally even if workers are still running - Set resource limits if needed using the 
resourceLimitsoption 
While Twerker attempts to support sibling functions and module imports, there are some limitations:
- Complex dependencies may not be fully serialized
 - Some modules with special requirements might need manual handling
 - Functions that rely on closure variables might not work as expected
 - Modules with 'this' binding issues (like some crypto methods) receive special handling
 
ISC
Dak Washbrook (@dakdevs on X)
Made with β€οΈ using TypeScript and Node.js