{"record":{"id":"9c2021ccb042b7ea","repo":"krahets/hello-algo","slug":"the-deque-is-empty-9c2021","errorCode":null,"errorMessage":"The Deque Is Empty.","messagePattern":"The Deque Is Empty\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ru/codes/typescript/chapter_stack_and_queue/array_deque.ts","lineNumber":88,"sourceCode":"    /* Извлечение из головы очереди */\n    popFirst(): number {\n        const num: number = this.peekFirst();\n        // Указатель головы сдвигается на одну позицию назад\n        this.front = this.index(this.front + 1);\n        this.queSize--;\n        return num;\n    }\n\n    /* Извлечение из хвоста очереди */\n    popLast(): number {\n        const num: number = this.peekLast();\n        this.queSize--;\n        return num;\n    }\n\n    /* Доступ к элементу в начале очереди */\n    peekFirst(): number {\n        if (this.isEmpty()) throw new Error('The Deque Is Empty.');\n        return this.nums[this.front];\n    }\n\n    /* Доступ к элементу в конце очереди */\n    peekLast(): number {\n        if (this.isEmpty()) throw new Error('The Deque Is Empty.');\n        // Вычислить индекс хвостового элемента\n        const last = this.index(this.front + this.queSize - 1);\n        return this.nums[last];\n    }\n\n    /* Вернуть массив для вывода */\n    toArray(): number[] {\n        // Преобразовывать только элементы списка в пределах фактической длины\n        const res: number[] = [];\n        for (let i = 0, j = this.front; i < this.queSize; i++, j++) {\n            res[i] = this.nums[this.index(j)];\n        }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/ru/codes/typescript/chapter_stack_and_queue/array_deque.ts#L70-L106","documentation":"Thrown by peekFirst() on an array-backed deque when the deque is empty. It guards the read nums[this.front] which would otherwise return undefined or stale data. peekFirst backs popFirst, so the same throw propagates from popFirst on an empty deque.","triggerScenarios":"Calling peekFirst() or popFirst() on a freshly constructed deque; calling them after all elements have been popped; off-by-one in a loop that consumes one more element than present.","commonSituations":"Deque-based sliding-window or BFS code that does not bound its pop count by the deque size; mixing pushFirst/popLast counts asymmetrically until empty.","solutions":["Check deque.isEmpty() before peekFirst()/popFirst().","Bound consumption loops by the deque's current size.","Wrap peekFirst in try/catch when an empty front is a legitimate control-flow signal.","Log the size before access during debugging to catch over-consumption."],"exampleFix":"// before\nconst head = deque.peekFirst(); // throws if empty\n\n// after\nconst head = deque.isEmpty() ? null : deque.peekFirst();","handlingStrategy":"validation","validationCode":"if (!deque.isEmpty()) {\n    const head = deque.peekFirst();\n}","typeGuard":null,"tryCatchPattern":"try {\n    const head = deque.peekFirst();\n} catch (e) {\n    if (e instanceof Error && e.message === 'The Deque Is Empty.') {\n        // empty front; handle gracefully\n    } else throw e;\n}","preventionTips":["Check isEmpty() before peekFirst()/popFirst().","Bound front-consumption loops by the deque's current size.","Keep pushFirst/popFirst counts balanced."],"tags":["deque","typescript","empty-state","circular-array","validation"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}