From af85b577f139469f53723f2a5efe7a43562a52ee Mon Sep 17 00:00:00 2001 From: Kir_Antipov Date: Fri, 30 Dec 2022 03:17:55 +0000 Subject: [PATCH] Made an interface for all key-value iterables out there --- src/utils/collections/key-value-iterable.ts | 24 +++++++++++++++++++ .../collections/key-value-iterable.spec.ts | 20 ++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/utils/collections/key-value-iterable.ts create mode 100644 tests/unit/utils/collections/key-value-iterable.spec.ts diff --git a/src/utils/collections/key-value-iterable.ts b/src/utils/collections/key-value-iterable.ts new file mode 100644 index 0000000..56250f7 --- /dev/null +++ b/src/utils/collections/key-value-iterable.ts @@ -0,0 +1,24 @@ +/** + * Represents an object that contains key-value pairs and exposes an `entries()` method + * to iterate over those pairs. + */ +export interface KeyValueIterable { + /** + * Returns an iterable containing the key-value pairs of the object. + */ + entries(): Iterable<[K, V]>; +} + +/** + * Type guard to check if the given object implements the {@link KeyValueIterable} interface. + * + * @template K - The key type. + * @template V - The value type. + * + * @param obj - The object to check. + * + * @returns `true` if the object implements the {@link KeyValueIterable} interface; otherwise, `false`. + */ +export function isKeyValueIterable(obj: unknown): obj is KeyValueIterable { + return typeof (obj as KeyValueIterable)?.entries === "function"; +} diff --git a/tests/unit/utils/collections/key-value-iterable.spec.ts b/tests/unit/utils/collections/key-value-iterable.spec.ts new file mode 100644 index 0000000..5ece133 --- /dev/null +++ b/tests/unit/utils/collections/key-value-iterable.spec.ts @@ -0,0 +1,20 @@ +import { isKeyValueIterable } from "@/utils/collections/key-value-iterable"; + +describe("isKeyValueIterable", () => { + test("returns true for objects that have entries", () => { + expect(isKeyValueIterable(new Map())).toBe(true); + expect(isKeyValueIterable(new Set())).toBe(true); + expect(isKeyValueIterable([])).toBe(true); + expect(isKeyValueIterable({ entries: () => [] })).toBe(true); + }); + + test("returns false for objects that has no entries", () => { + expect(isKeyValueIterable({})).toBe(false); + expect(isKeyValueIterable(new Date())).toBe(false); + }); + + test("returns false for null and undefined", () => { + expect(isKeyValueIterable(null)).toBe(false); + expect(isKeyValueIterable(undefined)).toBe(false); + }); +});