import { isMap, type Nullable } from './types.js'; /** * Similar to Map.has, but works for plain objects, and returns false * for null maps * @see Map.has */ export function has(obj: O, key: keyof O): boolean; /** * Similar to Map.has, but works for plain objects, and returns false * for null maps * @see Map.has */ export function has(obj: Map, key: K): boolean; export function has(obj: null | undefined, key: unknown): false; export function has(obj: Nullable>, key: any): boolean { return ( !!obj && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access (typeof (obj as any).has === 'function' ? (obj as Map).has(key) : key in (obj as object)) ); } export type MapValue = T extends Map ? V : never; export type ObjValue = O[K]; /** * Similar to Map.get, but works for plain objects, and returns undefined * for null maps and missing keys * @see Map.get * @returns found value, *undefined* if map/value to not exist */ export function get(obj: O, key: K): ObjValue; export function get>(obj: Nullable, key: K): MapValue; export function get(obj: Nullable | object>, key: any): any { if (obj) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return return typeof (obj as any).get === 'function' ? (obj as Map).get(key) : // @ts-expect-error definitely not a map or nullish obj[key as string]; } return; } /** * Returns a value by key, throws if the value is missing or the map null */ export function getValue(map: T, key: keyof T, errorMessage?: string): ObjValue; export function getValue>(map: T, key: K, errorMessage?: string): MapValue; export function getValue(map: T, key: unknown, errorMessage?: string): never; export function getValue | object, K, V>(map: Nullable, key: KeyOf, errorMessage?: string) { // @ts-expect-error hmm if (has(map, key)) { // @ts-expect-error hmmm return get(map, key); } throw new Error(errorMessage || `Missing map`); } type KeyOf = T extends Map ? K : T extends object ? keyof T : never; /** * @see Map.keys * @see Object.keys * @returns an iterable of the map/object keys */ export function keys>(map: O): Iterable; export function keys(map: O): Iterable; export function keys>(obj: O) { return isMap(obj) ? obj.keys() : Object.keys(obj); } /** * @see Map.values * @see Object.values */ export function values>(map: O): Iterable>; export function values(map: O): Iterable>; export function values>(obj: O) { return isMap(obj) ? obj.values() : Object.values(obj); }