@@ -171,20 +171,21 @@ export class TtlCache<K, V> extends Map<K, V>
171171 ) ;
172172 }
173173
174+ const abs = options ?. absoluteExpiration ;
175+ if ( abs !== undefined && ( ! ( abs >= 0 ) || ! Number . isFinite ( abs ) ) ) {
176+ throw new RangeError (
177+ `Cannot set entry in TtlCache: absoluteExpiration must be a finite, non-negative number: received ${ abs } ` ,
178+ ) ;
179+ }
180+
174181 const existing = this . #timeouts. get ( key ) ;
175182 if ( existing !== undefined ) clearTimeout ( existing ) ;
176183 super . set ( key , value ) ;
177184 this . #timeouts. set ( key , setTimeout ( ( ) => this . delete ( key ) , ttl ) ) ;
178185
179186 if ( this . #slidingExpiration) {
180187 this . #entryTtls! . set ( key , ttl ) ;
181- if ( options ?. absoluteExpiration !== undefined ) {
182- const abs = options . absoluteExpiration ;
183- if ( ! ( abs >= 0 ) || ! Number . isFinite ( abs ) ) {
184- throw new RangeError (
185- `Cannot set entry in TtlCache: absoluteExpiration must be a finite, non-negative number: received ${ abs } ` ,
186- ) ;
187- }
188+ if ( abs !== undefined ) {
188189 this . #absoluteDeadlines! . set ( key , Date . now ( ) + abs ) ;
189190 } else {
190191 this . #absoluteDeadlines! . delete ( key ) ;
@@ -223,6 +224,46 @@ export class TtlCache<K, V> extends Map<K, V>
223224 return super . get ( key ) ;
224225 }
225226
227+ /**
228+ * Returns the value associated with the given key, or `undefined` if the
229+ * key is not present, **without** resetting its TTL.
230+ *
231+ * This is the TTL-cache equivalent of
232+ * {@linkcode LruCache.prototype.peek | LruCache.peek()}: a side-effect-free
233+ * read that leaves the entry's expiration unchanged.
234+ *
235+ * @experimental **UNSTABLE**: New API, yet to be vetted.
236+ *
237+ * @param key The key to look up.
238+ * @returns The value, or `undefined` if not present.
239+ *
240+ * @example Peeking at a value without resetting the sliding TTL
241+ * ```ts
242+ * import { TtlCache } from "@std/cache/ttl-cache";
243+ * import { assertEquals } from "@std/assert/equals";
244+ * import { FakeTime } from "@std/testing/time";
245+ *
246+ * using time = new FakeTime(0);
247+ * const cache = new TtlCache<string, number>(100, {
248+ * slidingExpiration: true,
249+ * });
250+ *
251+ * cache.set("a", 1);
252+ * time.now = 80;
253+ *
254+ * // peek does not reset the TTL
255+ * assertEquals(cache.peek("a"), 1);
256+ *
257+ * // entry still expires at t=100
258+ * time.now = 100;
259+ * assertEquals(cache.peek("a"), undefined);
260+ * ```
261+ */
262+ peek ( key : K ) : V | undefined {
263+ if ( ! super . has ( key ) ) return undefined ;
264+ return super . get ( key ) ;
265+ }
266+
226267 /**
227268 * Deletes the value associated with the given key.
228269 *
0 commit comments