trekhleb/javascript-algorithms · error · TypeError
Cannot construct Heap instance directly
Error message
Cannot construct Heap instance directly
What it means
Heap is an abstract base class for MinHeap and MaxHeap; its ordering hook pairIsInCorrectOrder() is deliberately unimplemented (it always throws, Heap.js:280-285), so a bare Heap could never order elements. The constructor guard `new.target === Heap` (Heap.js:12-14) makes that contract explicit by throwing a TypeError the instant new Heap(...) runs - the same pattern as abstract-class enforcement in other languages.
Source
Thrown at src/data-structures/heap/Heap.js:13
import Comparator from '../../utils/comparator/Comparator';
/**
* Parent class for Min and Max Heaps.
*/
export default class Heap {
/**
* @constructs Heap
* @param {Function} [comparatorFunction]
*/
constructor(comparatorFunction) {
if (new.target === Heap) {
throw new TypeError('Cannot construct Heap instance directly');
}
// Array representation of the heap.
this.heapContainer = [];
this.compare = new Comparator(comparatorFunction);
}
/**
* @param {number} parentIndex
* @return {number}
*/
getLeftChildIndex(parentIndex) {
return (2 * parentIndex) + 1;
}
/**
* @param {number} parentIndex
* @return {number}View on GitHub (pinned to 85293e3e2b)
Solutions
- Instantiate a concrete subclass: new MinHeap(comparatorFunction) or new MaxHeap(comparatorFunction) - both accept an optional comparator, so custom ordering usually needs no subclass.
- For truly custom ordering, extend Heap and implement pairIsInCorrectOrder(first, second) (return first <= second for a min-heap), then instantiate your subclass.
- In a factory, default the class parameter to a concrete one: function makeHeap(Ctor = MinHeap) { return new Ctor(); }
- Check imports: Heap should never appear after `new` outside its own subclasses.
Example fix
// before import Heap from './heap/Heap'; const heap = new Heap((a, b) => a - b); // TypeError: Cannot construct Heap instance directly // after import MinHeap from './heap/MinHeap'; const heap = new MinHeap((a, b) => a - b);
Defensive patterns
Strategy: type-guard
Type guard
import Heap from '../heap/Heap';
import MinHeap from '../heap/MinHeap';
import MaxHeap from '../heap/MaxHeap';
// True only for constructors that may legally follow `new`
const isConcreteHeapClass = (Ctor) =>
Ctor === MinHeap || Ctor === MaxHeap || Ctor.prototype instanceof Heap;
function makeHeap(Ctor = MinHeap, comparator) {
if (!isConcreteHeapClass(Ctor)) {
throw new TypeError('Heap subclasses only; Heap itself is abstract');
}
return new Ctor(comparator);
} Try / catch
try {
heap = new HeapClass(comparator);
} catch (error) {
if (error instanceof TypeError && /Cannot construct Heap instance directly/.test(error.message)) {
heap = new MinHeap(comparator); // fall back to a concrete heap
} else {
throw error;
}
} Prevention
- Never write `new Heap(...)` - use MinHeap/MaxHeap; both accept an optional comparatorFunction.
- In TypeScript, declare `abstract class Heap` in a .d.ts so the compiler rejects direct construction.
- Factories should default to a concrete subclass, never the base class.
- When subclassing Heap, implement pairIsInCorrectOrder() immediately - it throws on first heapify otherwise.
When it happens
Trigger: new Heap() or new Heap((a, b) => a - b); a generic factory that receives the class by variable (new Ctor(cmp) where Ctor === Heap); importing Heap because it is the first hit when searching the package for 'heap'.
Common situations: Wanting 'just a heap' and instantiating the base class picked by an IDE auto-import; porting code from a library where Heap itself is concrete; factory code that defaults its class parameter to the base instead of a subclass.
Related errors
AI-assisted analysis of trekhleb/javascript-algorithms@85293e3e2b (2026-08-24).
Data as JSON: /api/errors/cdfb28ee57bb3e2d.
Report an issue: GitHub.