TypeScript Stack with Generics
stack-typescript is a lightweight, generic Stack data structure implementation for TypeScript and JavaScript environments, currently at version 1.0.4. It is built upon the `linked-list-typescript` package, providing a LIFO (Last-In, First-Out) collection. Key features include full TypeScript generics support for strong type-checking, enabling stacks of any primitive, object, or custom class. The package also implements both the JavaScript iterator and iterable protocols, allowing seamless integration with `for...of` loops, spread syntax (`...`), and array deconstruction. Its primary differentiators are its explicit use of a linked list for underlying storage and its full adherence to TypeScript's type-templating capabilities, ensuring type safety from initialization to manipulation. The release cadence appears stable, with a focus on core data structure functionality without frequent breaking changes, typical for foundational utility libraries.
Common errors
-
Argument of type 'string | number' is not assignable to parameter of type 'string'. Type 'number' is not assignable to type 'string'.
cause Attempting to initialize or push a value of a different type than the generic type parameter specified for the stack.fixEnsure all values provided to the stack (during instantiation or via `push`) strictly adhere to the generic type parameter. For mixed types, use `Stack<any>` or a union type if appropriate (e.g., `Stack<string | number>`). ```typescript // Wrong: let items: (string | number)[] = ['one', 'two', 3]; let stack = new Stack<string>(...items); // Correct: let items: (string | number)[] = ['one', 'two', 3]; let stack = new Stack<string | number>(...items); ```
Warnings
- gotcha When initializing a Stack with values (e.g., `new Stack<number>(...items)`), the items are pushed from left-to-right into the stack. This means the *first* argument provided will become the *top* of the stack, and the *last* argument will be at the *bottom*. This is inverse to how an array `push` would naturally order elements if interpreted as 'first in, first at bottom'.
- gotcha The Stack stores references to objects, not copies. Modifying an object retrieved from the stack (e.g., via `top` or `pop()`) will affect the object within the stack if it is later pushed back, or if other references to the same object exist.
- gotcha Using `new Stack()` without specifying a generic type parameter `<T>` will result in a stack of type `Stack<any>`. This will bypass TypeScript's type-checking and defeat the purpose of using a generic data structure.
Install
-
npm install stack-typescript -
yarn add stack-typescript -
pnpm add stack-typescript
Imports
- Stack
import Stack from 'stack-typescript';
import { Stack } from 'stack-typescript'; - Stack
const { Stack } = require('stack-typescript'); - Stack<T>
let myStack = new Stack();
let myStack = new Stack<string>();
Quickstart
import { Stack } from 'stack-typescript';
// Create an empty stack of numbers
let numberStack = new Stack<number>();
numberStack.push(10);
numberStack.push(20);
numberStack.push(30);
console.log(`Number Stack Size: ${numberStack.size}`); // Expected: 3
console.log(`Top of Number Stack: ${numberStack.top}`); // Expected: 30
// Initialize a stack with values and custom types
class Foo {
constructor(public val: number) {}
get bar(): number { return this.val; }
}
let foo1 = new Foo(100);
let foo2 = new Foo(200);
let fooStack = new Stack<Foo>(foo1, foo2, new Foo(300));
console.log(`Foo Stack Size: ${fooStack.size}`); // Expected: 3
console.log(`Top of Foo Stack: ${fooStack.top?.bar}`); // Expected: 100
let poppedFoo = fooStack.pop();
console.log(`Popped Foo: ${poppedFoo?.bar}`); // Expected: 100
console.log(`Foo Stack Size after pop: ${fooStack.size}`); // Expected: 2
// Iterate over the stack
console.log('Iterating over Foo Stack:');
for (let item of fooStack) {
console.log(item.bar);
}
// Expected: 200, 300