Skip to content

Commit

Permalink
feat[isPartialOf]: discover symbol properties in pred.predObj
Browse files Browse the repository at this point in the history
  • Loading branch information
Milly committed Aug 8, 2024
1 parent 56b24ed commit 33e9508
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
24 changes: 24 additions & 0 deletions is/__snapshots__/partial_of_test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,27 @@ snapshot[`isPartialOf<T> > returns properly named predicate function 2`] = `
d: asOptional(asReadonly(isString))
})"
`;
snapshot[`isPartialOf<T> > with symbol properties > returns properly named predicate function 1`] = `
"isObjectOf({
a: asOptional(isNumber),
Symbol(b): asOptional(isUnionOf([
isString,
isUndefined
])),
Symbol(c): asOptional(isBoolean),
Symbol(c): asOptional(asReadonly(isString))
})"
`;
snapshot[`isPartialOf<T> > with symbol properties > returns properly named predicate function 2`] = `
"isObjectOf({
a: asOptional(isNumber),
Symbol(b): asOptional(isUnionOf([
isString,
isUndefined
])),
Symbol(c): asOptional(isBoolean),
Symbol(c): asOptional(asReadonly(isString))
})"
`;
11 changes: 8 additions & 3 deletions is/partial_of.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ export function isPartialOf<
):
& Predicate<FlatType<Partial<T>>>
& IsPredObj<P> {
const predObj = Object.fromEntries(
Object.entries(pred.predObj).map(([k, v]) => [k, asOptional(v)]),
) as Record<PropertyKey, Predicate<unknown>>;
const keys = [
...Object.keys(pred.predObj),
...Object.getOwnPropertySymbols(pred.predObj),
];
const predObj: Record<PropertyKey, Predicate<unknown>> = { ...pred.predObj };
for (const key of keys) {
predObj[key] = asOptional(predObj[key]);
}
return isObjectOf(predObj) as
& Predicate<FlatType<Partial<T>>>
& IsPredObj<P>;
Expand Down
51 changes: 51 additions & 0 deletions is/partial_of_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,55 @@ Deno.test("isPartialOf<T>", async (t) => {
>(true);
}
});

await t.step("with symbol properties", async (t) => {
const b = Symbol("b");
const c = Symbol("c");
const d = Symbol("c");
const pred = is.ObjectOf({
a: is.Number,
[b]: is.UnionOf([is.String, is.Undefined]),
[c]: as.Optional(is.Boolean),
[d]: as.Readonly(is.String),
});

await t.step("returns properly named predicate function", async (t) => {
await assertSnapshot(t, isPartialOf(pred).name);
await assertSnapshot(t, isPartialOf(isPartialOf(pred)).name);
});

await t.step("returns true on Partial<T> object", () => {
assertEquals(
isPartialOf(pred)({ a: undefined, [b]: undefined, [c]: undefined }),
true,
);
assertEquals(isPartialOf(pred)({}), true);
});

await t.step("returns false on non Partial<T> object", () => {
assertEquals(isPartialOf(pred)("a"), false, "Value is not an object");
assertEquals(
isPartialOf(pred)({ a: 0, [b]: "a", [c]: "" }),
false,
"Object have a different type property",
);
});

await t.step("predicated type is correct", () => {
const a: unknown = { a: 0, [b]: "a", [c]: true };
if (isPartialOf(pred)(a)) {
assertType<
Equal<
typeof a,
Partial<{
a: number;
[b]: string;
[c]: boolean;
readonly [d]: string;
}>
>
>(true);
}
});
});
});

0 comments on commit 33e9508

Please sign in to comment.