diff --git a/is/object_of.ts b/is/object_of.ts index 7be8ca9..786f32b 100644 --- a/is/object_of.ts +++ b/is/object_of.ts @@ -9,7 +9,7 @@ import { import type { Predicate } from "../type.ts"; /** - * Return a type predicate function that returns `true` if the type of `x` is `ObjectOf`. + * Return a type predicate function that returns `true` if the type of `x` is/has `ObjectOf`. * * Use {@linkcode isRecordOf} if you want to check if the type of `x` is a record of `T`. * @@ -34,6 +34,12 @@ import type { Predicate } from "../type.ts"; * if (isMyType(a)) { * const _: { a: number; b: string; c?: boolean | undefined, readonly d: string } = a; * } + * + * // It also works for value with Object.assign + * const b: unknown = Object.assign(100, { a: 0, b: "a", d: "d" }); + * if (isMyType(b)) { + * const _: { a: number; b: string; c?: boolean | undefined, readonly d: string } = b; + * } * ``` */ export function isObjectOf< @@ -45,7 +51,7 @@ export function isObjectOf< ].map((k) => [k, predObj[k]]); const pred = rewriteName( (x): x is ObjectOf => { - if (!isObject(x)) return false; + if (x == null) return false; return preds.every(([k, pred]) => pred(x[k])); }, "isObjectOf", @@ -54,13 +60,6 @@ export function isObjectOf< return annotate(pred, "predObj", predObj); } -function isObject(x: unknown): x is Record { - if (x == null) return false; - if (typeof x !== "object" && typeof x !== "function") return false; - if (Array.isArray(x)) return false; - return true; -} - type ObjectOf>> = FlatType< // Readonly/Optional & { diff --git a/is/object_of_test.ts b/is/object_of_test.ts index 514ef4b..00e301c 100644 --- a/is/object_of_test.ts +++ b/is/object_of_test.ts @@ -33,12 +33,30 @@ Deno.test("isObjectOf", async (t) => { true, "Undefined properties are ignored", ); + }); + + await t.step("returns true on value with T object assigned", () => { + const v = { a: 0, b: "a", c: true }; + // Only 'null' and 'undefined' are not Object.assign-able + assertEquals( + isObjectOf(predObj)(Object.assign("string", v)), + true, + "string", + ); + assertEquals(isObjectOf(predObj)(Object.assign(100, v)), true, "number"); + assertEquals(isObjectOf(predObj)(Object.assign(100n, v)), true, "bigint"); + assertEquals(isObjectOf(predObj)(Object.assign(true, v)), true, "boolean"); + assertEquals(isObjectOf(predObj)(Object.assign([], v)), true, "array"); + assertEquals(isObjectOf(predObj)(Object.assign({}, v)), true, "object"); + assertEquals( + isObjectOf(predObj)(Object.assign(() => {}, v)), + true, + "function", + ); assertEquals( - isObjectOf(predObj)( - Object.assign(() => void 0, { a: 0, b: "a", c: true }), - ), + isObjectOf(predObj)(Object.assign(Symbol("symbol"), v)), true, - "Function are treated as an object", + "symbol", ); });