@manoruchan/extended-map
v2.1.0
Published
An extended Map for TypeScript with Java-style utility methods.
Maintainers
Readme
extended-map
Enhanced Map
EnMap is an enhanced Map implementation that provides Java-inspired methods such as compute and merge.
Migration Notice: EnMap is the successor to ExtMap. ExtMap is now deprecated and will be removed in v3.0.0.
Features
Java-like operations Powerful methods that adapt their behavior based on whether a value exists or is nullish. (
compute,computeIfPresent,computeIfAbsent,merge)Nullish value handling Treats both
undefined(returned byMap.get(key)) andnullas lack of value in most operationsnullcan exist, but is considered absent when acted upon. The entry will be removed ifcomputeormergereturnsnullorundefined.Utility methods Provides convenient array-like utilities such as
filter,sweep,some,every.
Installation
npm install @manoruchan/extended-mapUsage
Example computeIfAbsent
import { EnMap } from "@manoruchan/extended-map";
const cache = new EnMap<string, string>();
// Executes the mapping function and stores the result
// only if the key does not already exist.
const data1 = cache.computeIfAbsent("user:02", () => {
// do something like fetching DB...
return "Alice";
});
// The key is already existing, so the mapping function won't be executed.
const data2 = cache.computeIfAbsent("user:02", () => {
// do something like fetching DB...
return "Bob";
});
// data1 === "Alice"
// data2 === "Alice"
Example nested enmap
// <username, <command, timestamp>>
const cooldowns = new EnMap<string, EnMap<string, number>>();
const now = Date.now();
const COOLDOWN_MS = 3000;
cooldowns
.computeIfAbsent("Alice", _ => new EnMap<string, number>())
.set("ping", now + COOLDOWN_MS);
const pingCooldown = cooldowns.get("Alice")?.get("ping");
if (pingCooldown !== undefined) {
console.log(pingCooldown > now); // true
}Example merge
const wordCounts = new EnMap<string, number>();
// Absent
wordCounts.merge("apple", 1, (oldV, newV) => oldV + newV);
// Present
wordCounts.merge("apple", 1, (oldV, newV) => oldV + newV);
// Present
wordCounts.merge("apple", 1, (oldV, newV) => oldV + newV);
// Result: 3
console.log(wordCounts.get("apple"));Example computeIfPresent
const items = new EnMap<string, number>();
items.set("mana_potion", 5);
// Reduce item amounts
items.computeIfPresent("mana_potion", (_, oldV) => oldV - 1);
console.log(items.get("mana_potion")); // 4
// Deleted from map due to mapping function returns undefined
items.computeIfPresent("mana_potion", (_, oldV) => {
if (oldV - 4 === 0) {
return undefined;
}
});
console.log(items.has("mana_potion")); // falseAPI Reference (Primary Methods)
compute(key, fn): Optional<V> — Computes based on the mapping function, regardless of key existence.
computeIfAbsent(key, fn): V — Set the value if the key is not exist or assigned as null.
computeIfPresent(key, fn): Optional<V> — Computes if the key exists. Deletes if fn returns nullish.
merge(key, value, fn): Optional<V> — Set the value if the key is not exist, otherwise merge by fn. Deletes if fn returns nullish.
delete(key, value?): boolean — Deletes the entry if key and value matched.
getOrDefault(key, defaultValue): V — Returns defaultValue if the key does not exist. If the value is null, returns null.
sweep(fn): V[] — Deletes all entries satisfies condition and returns an array of removed values.
Optional Type
// Used internally to represent values that may be missing or nullish.
export type Optional<Type> = Type | undefined | null;