isaacscript-common
Version:
Helper functions and features for IsaacScript mods.
140 lines (126 loc) • 3.88 kB
text/typescript
import type { DefaultMap } from "../classes/DefaultMap";
import { sumArray } from "./array";
/** Helper function to copy a map. (You can also use a Map constructor to accomplish this task.) */
// eslint-disable-next-line complete/no-mutable-return
export function copyMap<K, V>(oldMap: ReadonlyMap<K, V>): Map<K, V> {
const newMap = new Map<K, V>();
for (const [key, value] of oldMap) {
newMap.set(key, value);
}
return newMap;
}
/**
* Helper function to get the value from a `DefaultMap` that corresponds to an entity, assuming that
* the map uses `PtrHash` as an index.
*/
export function defaultMapGetHash<V, A extends unknown[]>(
map: DefaultMap<PtrHash, V, A>,
entity: Entity,
...extraArgs: A
): V {
const ptrHash = GetPtrHash(entity);
return map.getAndSetDefault(ptrHash, ...extraArgs);
}
/**
* Helper function to set a value for a `DefaultMap` that corresponds to an entity, assuming that
* the map uses `PtrHash` as an index.
*
* Since `Map` and `DefaultMap` set values in the same way, this function is simply an alias for the
* `mapSetHash` helper function.
*/
export function defaultMapSetHash<V>(
// eslint-disable-next-line complete/prefer-readonly-parameter-types
map: Map<PtrHash, V>,
entity: Entity,
value: V,
): void {
mapSetHash(map, entity, value);
}
/**
* Helper function to get a copy of a map with the keys and the values reversed.
*
* For example:
*
* ```ts
* new Map<string, number>([
* ["foo", 1],
* ["bar", 2],
* ]);
* ```
*
* Would be reversed to:
*
* ```ts
* new Map<number, string>([
* [1, "foo"],
* [2, "bar"],
* ]);
* ```
*/
export function getReversedMap<K, V>(
map: ReadonlyMap<K, V>,
): ReadonlyMap<V, K> {
const reverseMap = new Map<V, K>();
for (const [key, value] of map) {
reverseMap.set(value, key);
}
return reverseMap;
}
/**
* Helper function to set a value for a `DefaultMap` that corresponds to an entity, assuming that
* the map uses `PtrHash` as an index.
*/
export function mapSetHash<V>(
// eslint-disable-next-line complete/prefer-readonly-parameter-types
map: Map<PtrHash, V>,
entity: Entity,
value: V,
): void {
const hash = GetPtrHash(entity);
map.set(hash, value);
}
/**
* Helper function to convert an object to a map.
*
* This is useful when you need to construct a type safe object with the `satisfies` operator, but
* then later on you need to query it in a way where you expect the return value to be T or
* undefined. In this situation, by converting the object to a map, you can avoid unsafe type
* assertions.
*
* Note that the map values will be inserted in a random order, due to how `pairs` works under the
* hood.
*
* Also see the `objectToReadonlyMap` function.
*/
export function objectToMap<K extends string | number | symbol, V>(
object: Record<K, V>,
): ReadonlyMap<K, V> {
const map = new Map<K, V>();
for (const [key, value] of Object.entries(object)) {
map.set(key as K, value as V);
}
return map;
}
/**
* Helper function to convert an object to a read-only map.
*
* This is useful when you need to construct a type safe object with the `satisfies` operator, but
* then later on you need to query it in a way where you expect the return value to be T or
* undefined. In this situation, by converting the object to a map, you can avoid unsafe type
* assertions.
*
* Note that the map values will be inserted in a random order, due to how `pairs` works under the
* hood.
*
* Also see the `objectToMap` function.
*/
export function objectToReadonlyMap<K extends string | number | symbol, V>(
object: Record<K, V>,
): ReadonlyMap<K, V> {
return objectToMap(object);
}
/** Helper function to sum every value in a map together. */
export function sumMap(map: ReadonlyMap<unknown, number>): number {
const values = [...map.values()];
return sumArray(values);
}