Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 2071bf2

Browse files
committed
Fix type issues
1 parent df3b20b commit 2071bf2

File tree

2 files changed

+121
-80
lines changed

2 files changed

+121
-80
lines changed

src/utils/LruCache.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export class LruCache<K, V> {
9393
return;
9494
}
9595

96-
const newItem = {
96+
const newItem: CacheItem<K, V> = {
9797
key,
9898
value,
9999
next: null,
@@ -106,21 +106,14 @@ export class LruCache<K, V> {
106106
newItem.next = this.head;
107107
}
108108

109-
this.head = newItem;
110-
111-
if (!this.tail) {
112-
// This is the first item added to the list. Also set it as tail.
113-
this.tail = newItem;
114-
}
109+
this.setHeadTail(newItem);
115110

116111
// Store item in lookup map.
117112
this.map.set(key, newItem);
118113

119114
if (this.map.size > this.capacity) {
120115
// Map size exceeded cache capcity. Drop tail item.
121-
this.map.delete(this.tail.key);
122-
this.tail = this.tail.prev;
123-
this.tail.next = null;
116+
this.delete(this.tail.key);
124117
}
125118
}
126119

@@ -159,15 +152,33 @@ export class LruCache<K, V> {
159152
if (item === this.head) return item;
160153

161154
this.removeItemFromList(item);
162-
// …and put it to the front.
163-
this.head.prev = item;
155+
156+
// Put item to the front.
157+
158+
if (this.head) {
159+
this.head.prev = item;
160+
}
161+
164162
item.prev = null;
165163
item.next = this.head;
166-
this.head = item;
164+
165+
this.setHeadTail(item);
167166

168167
return item;
169168
}
170169

170+
private setHeadTail(item: CacheItem<K, V>): void {
171+
if (item.prev === null) {
172+
// Item has no previous item → head
173+
this.head = item;
174+
}
175+
176+
if (item.next === null) {
177+
// Item has no next item → tail
178+
this.tail = item;
179+
}
180+
}
181+
171182
private removeItemFromList(item: CacheItem<K, V>): void {
172183
if (item === this.head) {
173184
this.head = item.next ?? null;

test/utils/LruCache-test.ts

Lines changed: 97 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ describe("LruCache", () => {
4848
expect(Array.from(cache.values())).toEqual([]);
4949
});
5050

51+
it("delete() should not raise an error", () => {
52+
cache.delete("a");
53+
});
54+
5155
describe("when the cache contains 2 items", () => {
5256
beforeEach(() => {
5357
cache.set("a", "a value");
@@ -65,94 +69,120 @@ describe("LruCache", () => {
6569
it("values() should return the items in the cache", () => {
6670
expect(Array.from(cache.values())).toEqual(["a value", "b value"]);
6771
});
68-
});
69-
70-
describe("when the cache contains 3 items", () => {
71-
beforeEach(() => {
72-
cache.set("a", "a value");
73-
cache.set("b", "b value");
74-
cache.set("c", "c value");
75-
});
7672

77-
it("deleting an unkonwn item should not raise an error", () => {
78-
cache.delete("unknown");
79-
});
80-
81-
it("deleting the first item should work", () => {
82-
cache.delete("a");
83-
expect(Array.from(cache.values())).toEqual(["b value", "c value"]);
84-
});
85-
86-
it("deleting the item in the middle should work", () => {
87-
cache.delete("b");
88-
expect(Array.from(cache.values())).toEqual(["a value", "c value"]);
89-
});
73+
describe("and adding another item", () => {
74+
beforeEach(() => {
75+
cache.set("c", "c value");
76+
});
9077

91-
it("deleting the last item should work", () => {
92-
cache.delete("c");
93-
expect(Array.from(cache.values())).toEqual(["a value", "b value"]);
94-
});
78+
it("deleting an unkonwn item should not raise an error", () => {
79+
cache.delete("unknown");
80+
});
9581

96-
it("deleting and adding some items should work", () => {
97-
cache.set("d", "d value");
98-
cache.get("b");
99-
cache.delete("b");
100-
cache.set("e", "e value");
101-
expect(Array.from(cache.values())).toEqual(["c value", "d value", "e value"]);
102-
});
82+
it("deleting the first item should work", () => {
83+
cache.delete("a");
84+
expect(Array.from(cache.values())).toEqual(["b value", "c value"]);
10385

104-
describe("and accesing the first added item and adding another item", () => {
105-
beforeEach(() => {
106-
cache.get("a");
86+
// add an item after delete should work work
10787
cache.set("d", "d value");
88+
expect(Array.from(cache.values())).toEqual(["b value", "c value", "d value"]);
10889
});
10990

110-
it("should contain the last recently accessed items", () => {
111-
expect(cache.has("a")).toBe(true);
112-
expect(cache.get("a")).toEqual("a value");
113-
expect(cache.has("c")).toBe(true);
114-
expect(cache.get("c")).toEqual("c value");
115-
expect(cache.has("d")).toBe(true);
116-
expect(cache.get("d")).toEqual("d value");
91+
it("deleting the item in the middle should work", () => {
92+
cache.delete("b");
93+
expect(Array.from(cache.values())).toEqual(["a value", "c value"]);
94+
95+
// add an item after delete should work work
96+
cache.set("d", "d value");
11797
expect(Array.from(cache.values())).toEqual(["a value", "c value", "d value"]);
11898
});
11999

120-
it("should not contain the least recently accessed items", () => {
121-
expect(cache.has("b")).toBe(false);
122-
expect(cache.get("b")).toBeUndefined();
123-
});
124-
});
100+
it("deleting the last item should work", () => {
101+
cache.delete("c");
102+
expect(Array.from(cache.values())).toEqual(["a value", "b value"]);
125103

126-
describe("and adding 2 additional items", () => {
127-
beforeEach(() => {
104+
// add an item after delete should work work
128105
cache.set("d", "d value");
129-
cache.set("e", "e value");
106+
expect(Array.from(cache.values())).toEqual(["a value", "b value", "d value"]);
130107
});
131108

132-
it("has() should return false for expired items", () => {
133-
expect(cache.has("a")).toBe(false);
134-
expect(cache.has("b")).toBe(false);
135-
});
109+
it("deleting all items should work", () => {
110+
cache.delete("a");
111+
cache.delete("b");
112+
cache.delete("c");
113+
// should not raise an error
114+
cache.delete("a");
115+
cache.delete("b");
116+
cache.delete("c");
136117

137-
it("has() should return true for items in the caceh", () => {
138-
expect(cache.has("c")).toBe(true);
139-
expect(cache.has("d")).toBe(true);
140-
expect(cache.has("e")).toBe(true);
118+
expect(Array.from(cache.values())).toEqual([]);
119+
120+
// add an item after delete should work work
121+
cache.set("d", "d value");
122+
expect(Array.from(cache.values())).toEqual(["d value"]);
141123
});
142124

143-
it("get() should return undefined for expired items", () => {
144-
expect(cache.get("a")).toBeUndefined();
145-
expect(cache.get("b")).toBeUndefined();
125+
it("deleting and adding some items should work", () => {
126+
cache.set("d", "d value");
127+
cache.get("b");
128+
cache.delete("b");
129+
cache.set("e", "e value");
130+
expect(Array.from(cache.values())).toEqual(["c value", "d value", "e value"]);
146131
});
147132

148-
it("get() should return the items in the cache", () => {
149-
expect(cache.get("c")).toBe("c value");
150-
expect(cache.get("d")).toBe("d value");
151-
expect(cache.get("e")).toBe("e value");
133+
describe("and accesing the first added item and adding another item", () => {
134+
beforeEach(() => {
135+
cache.get("a");
136+
cache.set("d", "d value");
137+
});
138+
139+
it("should contain the last recently accessed items", () => {
140+
expect(cache.has("a")).toBe(true);
141+
expect(cache.get("a")).toEqual("a value");
142+
expect(cache.has("c")).toBe(true);
143+
expect(cache.get("c")).toEqual("c value");
144+
expect(cache.has("d")).toBe(true);
145+
expect(cache.get("d")).toEqual("d value");
146+
expect(Array.from(cache.values())).toEqual(["a value", "c value", "d value"]);
147+
});
148+
149+
it("should not contain the least recently accessed items", () => {
150+
expect(cache.has("b")).toBe(false);
151+
expect(cache.get("b")).toBeUndefined();
152+
});
152153
});
153154

154-
it("values() should return the items in the cache", () => {
155-
expect(Array.from(cache.values())).toEqual(["c value", "d value", "e value"]);
155+
describe("and adding 2 additional items", () => {
156+
beforeEach(() => {
157+
cache.set("d", "d value");
158+
cache.set("e", "e value");
159+
});
160+
161+
it("has() should return false for expired items", () => {
162+
expect(cache.has("a")).toBe(false);
163+
expect(cache.has("b")).toBe(false);
164+
});
165+
166+
it("has() should return true for items in the caceh", () => {
167+
expect(cache.has("c")).toBe(true);
168+
expect(cache.has("d")).toBe(true);
169+
expect(cache.has("e")).toBe(true);
170+
});
171+
172+
it("get() should return undefined for expired items", () => {
173+
expect(cache.get("a")).toBeUndefined();
174+
expect(cache.get("b")).toBeUndefined();
175+
});
176+
177+
it("get() should return the items in the cache", () => {
178+
expect(cache.get("c")).toBe("c value");
179+
expect(cache.get("d")).toBe("d value");
180+
expect(cache.get("e")).toBe("e value");
181+
});
182+
183+
it("values() should return the items in the cache", () => {
184+
expect(Array.from(cache.values())).toEqual(["c value", "d value", "e value"]);
185+
});
156186
});
157187
});
158188
});

0 commit comments

Comments
 (0)