From 149430bbe9de18b1b194c28d0eb60449e27ab85e Mon Sep 17 00:00:00 2001 From: Kir_Antipov Date: Mon, 15 May 2023 09:21:15 +0000 Subject: [PATCH] Implemented `getSafe` method --- src/utils/reflection/index.ts | 1 + src/utils/reflection/object-reflector.ts | 23 ++++++++ .../utils/reflection/object-reflector.spec.ts | 55 +++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/src/utils/reflection/index.ts b/src/utils/reflection/index.ts index 815bc53..8d43ac6 100644 --- a/src/utils/reflection/index.ts +++ b/src/utils/reflection/index.ts @@ -30,4 +30,5 @@ export { getOwnEntries, merge, + getSafe, } from "./object-reflector"; diff --git a/src/utils/reflection/object-reflector.ts b/src/utils/reflection/object-reflector.ts index 8e20c4f..54324c1 100644 --- a/src/utils/reflection/object-reflector.ts +++ b/src/utils/reflection/object-reflector.ts @@ -205,3 +205,26 @@ export function merge(...values: T): UnionToIntersection(target: T, key: K): (K extends keyof T ? T[K] : unknown) | undefined { + if (target === null || target === undefined) { + return undefined; + } + + try { + return target[key as string]; + } catch { + return undefined; + } +} diff --git a/tests/unit/utils/reflection/object-reflector.spec.ts b/tests/unit/utils/reflection/object-reflector.spec.ts index 286a7b8..6aa2427 100644 --- a/tests/unit/utils/reflection/object-reflector.spec.ts +++ b/tests/unit/utils/reflection/object-reflector.spec.ts @@ -9,6 +9,7 @@ import { getAllValues, getOwnEntries, getPropertyDescriptor, + getSafe, merge, } from "@/utils/reflection/object-reflector"; @@ -195,3 +196,57 @@ describe("merge", () => { expect(Object.getOwnPropertyDescriptor(merged, "b")).toEqual(Object.getOwnPropertyDescriptor(obj2, "b")); }); }); + +describe("getSafe", () => { + it("returns the value of an existing property", () => { + const obj = { + name: "John", + age: 30, + }; + + expect(getSafe(obj, "name")).toBe("John"); + expect(getSafe(obj, "age")).toBe(30); + }); + + it("handles array indices as keys", () => { + const arr = ["apple", "banana", "cherry"] as const; + + expect(getSafe(arr, 0)).toBe("apple"); + expect(getSafe(arr, 1)).toBe("banana"); + expect(getSafe(arr, 2)).toBe("cherry"); + expect(getSafe(arr, 3)).toBeUndefined(); + }); + + it("handles Symbols as keys", () => { + const obj = { + [Symbol.toStringTag]: "Not Object", + }; + + expect(getSafe(obj, Symbol.toStringTag)).toBe("Not Object"); + }); + + it("returns undefined for non-existent properties", () => { + const obj = { + name: "John", + age: 30, + }; + + expect(getSafe(obj, "address")).toBeUndefined(); + expect(getSafe(obj, "salary")).toBeUndefined(); + }); + + it("returns undefined if accessing the property is not possible", () => { + const obj = { + get name(): string { + throw new Error(); + } + }; + + expect(getSafe(obj, "name")).toBeUndefined(); + }); + + it("returns undefined when the target object is null or undefined", () => { + expect(getSafe(null, "name")).toBeUndefined(); + expect(getSafe(undefined, "name")).toBeUndefined(); + }); +});