How to make cache with string keys without memory leak?

The problem is that the ordinary Map would prevent old cache entries from being garbage collected and the WeakMap won’t allow string as key.

Cache could be cleared by GC when the GC decides that there’s not enough free memory, cleared fully or partially, in arbitrary order.

Use case – optimisation for calculating custom hash codes for strings, used in custom HashMap, HashSet, Unique, etc.

Not working code, playground

const cache = new WeakMap<string, number>() // <= Error primitives can't be keys

function cachedCalculation(s: string) {
  let v = cache.get(s)
  if (v == undefined) {
    v = complexCalculation(s)
    cache.set(s, v)
  }
  return v
}

function complexCalculation(s: string): number {
  console.log(`complex calculation for ${s}`)
  return s.length
}

console.log(cachedCalculation('a'))
console.log(cachedCalculation('a'))

Possible solution, wonder if there’s something more sensible and also simple.

const cache = new Map<string, number>()
setInterval(() => cache.clear(), 1000)