@@ -7,7 +7,7 @@ Zero dependencies (**React optional**) — perfect for logs, streaming data, rol
77
88## Features
99
10- - 🔄 ** CircularBuffer (Low-level)** — direction-based circular buffer primitive (FRONT/BACK )
10+ - 🔄 ** CircularBuffer (Low-level)** — direction-based circular buffer primitive (HEAD/TAIL )
1111- 📦 ** BufferManager (High-level)** — convenient API (push/pop single or arrays, peek helpers, utilities)
1212- ⚛️ ** React Hook** — ` useCircularBuffer ` for automatic re-rendering in React
1313- 🎯 ** Type-Safe** — full TypeScript generics support
@@ -48,26 +48,26 @@ import { CircularBuffer, Direction } from "circular-queue-react";
4848
4949const buf = new CircularBuffer <string >(3 );
5050
51- // Push to BACK (newest side)
52- buf .push (" A" , Direction .BACK );
53- buf .push (" B" , Direction .BACK );
51+ // Push to TAIL (newest side)
52+ buf .push (" A" , Direction .TAIL );
53+ buf .push (" B" , Direction .TAIL );
5454
55- // Push to FRONT (oldest side)
56- buf .push (" Z" , Direction .FRONT );
55+ // Push to HEAD (oldest side)
56+ buf .push (" Z" , Direction .HEAD );
5757
58- console .log (buf .get (Direction .FRONT )); // "Z" (oldest)
59- console .log (buf .get (Direction .BACK )); // "B" (newest)
58+ console .log (buf .get (Direction .HEAD )); // "Z" (oldest)
59+ console .log (buf .get (Direction .TAIL )); // "B" (newest)
6060
6161// Peek many
62- console .log (buf .get (Direction .FRONT , 2 )); // ["Z","A"] (oldest -> newer)
63- console .log (buf .get (Direction .BACK , 2 )); // ["B","A"] (newest -> older)
62+ console .log (buf .get (Direction .HEAD , 2 )); // ["Z","A"] (oldest -> newer)
63+ console .log (buf .get (Direction .TAIL , 2 )); // ["B","A"] (newest -> older)
6464
6565// Iterate (oldest -> newest)
6666for (const x of buf ) console .log (x );
6767
6868// Pop
69- console .log (buf .pop (Direction .FRONT )); // removes oldest ("Z")
70- console .log (buf .pop (Direction .BACK )); // removes newest ("B")
69+ console .log (buf .pop (Direction .HEAD )); // removes oldest ("Z")
70+ console .log (buf .pop (Direction .TAIL )); // removes newest ("B")
7171
7272// Resize (logical capacity)
7373buf .resize (10 );
@@ -90,11 +90,11 @@ import { BufferManager } from "circular-queue-react";
9090
9191const b = new BufferManager <string >(3 );
9292
93- // pushTail keeps newest at the end (BACK )
93+ // pushTail keeps newest at the end (TAIL )
9494b .pushTail ([" A" , " B" , " C" , " D" ]);
9595console .log (b .getAll ()); // ["B","C","D"] (keeps last 3)
9696
97- // pushHead inserts at FRONT , preserves input order
97+ // pushHead inserts at HEAD , preserves input order
9898b .pushHead ([" X" , " Y" ]);
9999console .log (b .getAll ()); // ["X","Y","B"] (oldest -> newest)
100100
@@ -124,7 +124,7 @@ buf.pushTail([1, 2, 3, 4]); // keeps [2,3,4]
124124
125125### 4) React Hook
126126
127- ` useCircularBuffer ` provides a BufferManager-backed stateful hook:
127+ ` useCircularBuffer ` provides a BufferManager-TAILed stateful hook:
128128
129129- data auto-updates after mutations
130130- ` pushHead ` / ` pushTail ` / ` popHead ` / ` popTail ` / ` replaceAll ` / ` clear ` / ` resize `
@@ -178,13 +178,72 @@ This library uses consistent ordering rules:
178178
179179---
180180
181+ ## Important Type Limitation
182+
183+ ** ⚠️ When ` T ` itself is an array type, the array overload for ` pushHead ` /` pushTail ` cannot be used.**
184+
185+ ### Why?
186+
187+ TypeScript cannot distinguish between:
188+ - ` T ` (when ` T = number[] ` )
189+ - ` readonly T[] ` (which would be ` readonly number[][] ` )
190+
191+ Both resolve to array types, making overload resolution ambiguous.
192+
193+ ### Example
194+
195+ ``` ts
196+ // ❌ PROBLEMATIC: T = number[]
197+ const buf = new BufferManager <number []>(5 );
198+
199+ // This will fail! TypeScript cannot tell if you mean:
200+ // 1. Push a single item (which happens to be an array): number[]
201+ // 2. Push multiple items: readonly number[][]
202+ buf .pushTail ([[1 , 2 ], [3 , 4 ]]);
203+
204+ // ✅ SOLUTION: Push one item at a time
205+ buf .pushTail ([1 , 2 ]); // Push single array
206+ buf .pushTail ([3 , 4 ]); // Push another single array
207+ ```
208+
209+ ### Workaround
210+
211+ When ` T ` is an array type, ** always push items one at a time** instead of using the array overload:
212+
213+ ``` ts
214+ const items: number [][] = [[1 , 2 ], [3 , 4 ], [5 , 6 ]];
215+
216+ // ❌ Don't do this:
217+ // buf.pushTail(items);
218+
219+ // ✅ Do this instead:
220+ for (const item of items ) {
221+ buf .pushTail (item );
222+ }
223+
224+ // Or use a wrapper type:
225+ type Item = { data: number [] };
226+ const typedBuf = new BufferManager <Item >(5 );
227+ typedBuf .pushTail ([
228+ { data: [1 , 2 ] },
229+ { data: [3 , 4 ] }
230+ ]); // ✅ Works!
231+ ```
232+
233+ This limitation applies to:
234+ - ` BufferManager.pushHead() `
235+ - ` BufferManager.pushTail() `
236+ - ` useCircularBuffer ` hook's ` pushHead ` and ` pushTail `
237+
238+ ---
239+
181240## API Reference
182241
183242### Direction
184243
185244``` ts
186- Direction .FRONT ; // head / oldest side
187- Direction .BACK ; // tail / newest side
245+ Direction .HEAD ; // head / oldest side
246+ Direction .TAIL ; // tail / newest side
188247```
189248
190249### CircularBuffer` <T> `
@@ -198,7 +257,7 @@ Direction.BACK; // tail / newest side
198257- ` push(item: T, direction: Direction): void `
199258- ` pop(direction: Direction): T | undefined `
200259- ` get(direction: Direction): T | undefined `
201- - ` get(direction: Direction, count: number): T[] ` FRONT count: oldest → newer, BACK count: newest → older
260+ - ` get(direction: Direction, count: number): T[] ` HEAD count: oldest → newer, TAIL count: newest → older
202261
203262- ` clear(): void `
204263- ` resize(newCapacity: number): void ` (logical capacity)
0 commit comments