Implement a Generic Stack in TypeScript
This challenge requires you to implement a fundamental data structure: a Stack. A Stack follows the Last-In, First-Out (LIFO) principle, meaning the last element added is the first one to be removed. Implementing this as a generic class will allow it to store elements of any data type, making it highly reusable.
Problem Description
You need to create a Stack class in TypeScript that can store elements of any type. This generic Stack class should support the following core operations:
push(item: T): Adds an item of typeTto the top of the stack.pop(): T | undefined: Removes and returns the item from the top of the stack. If the stack is empty, it should returnundefined.peek(): T | undefined: Returns the item from the top of the stack without removing it. If the stack is empty, it should returnundefined.isEmpty(): boolean: Returnstrueif the stack contains no elements, andfalseotherwise.size(): number: Returns the current number of elements in the stack.
The class should be implemented using TypeScript's generic capabilities, allowing you to specify the type of elements the stack will hold (e.g., Stack<number>, Stack<string>, Stack<UserObject>).
Examples
Example 1: Stack of Numbers
const numberStack = new Stack<number>();
numberStack.push(10);
numberStack.push(20);
console.log(numberStack.peek()); // Output: 20
console.log(numberStack.pop()); // Output: 20
console.log(numberStack.size()); // Output: 1
console.log(numberStack.pop()); // Output: 10
console.log(numberStack.isEmpty()); // Output: true
Explanation:
We create a stack for numbers. We push 10, then 20. peek() returns 20 without removing it. pop() removes and returns 20. The size is now 1. Another pop() removes and returns 10, leaving the stack empty. isEmpty() confirms it's empty.
Example 2: Stack of Strings
const stringStack = new Stack<string>();
stringStack.push("apple");
stringStack.push("banana");
console.log(stringStack.pop()); // Output: "banana"
stringStack.push("cherry");
console.log(stringStack.peek()); // Output: "cherry"
Explanation:
We create a stack for strings. We push "apple", then "banana". pop() returns "banana". We then push "cherry". peek() returns "cherry".
Example 3: Empty Stack Operations
const emptyStack = new Stack<boolean>();
console.log(emptyStack.isEmpty()); // Output: true
console.log(emptyStack.pop()); // Output: undefined
console.log(emptyStack.peek()); // Output: undefined
console.log(emptyStack.size()); // Output: 0
Explanation:
Demonstrates the behavior of pop() and peek() on an empty stack, as well as isEmpty() and size().
Constraints
- The
Stackclass must be implemented as a generic class. - The underlying storage mechanism for the stack can be an array.
- All methods should be implemented correctly according to the LIFO principle.
- The
pop()andpeek()methods should handle an empty stack gracefully by returningundefined.
Notes
- Consider how to initialize the stack's internal storage.
- Think about the return type for
pop()andpeek()when the stack is empty. - TypeScript's generics (
<T>) will be crucial for making this class reusable with different data types.