Allow optional shape entries

This commit is contained in:
Endeavorance 2025-05-21 15:40:55 -04:00
parent 5ce10bed57
commit 26db320717
2 changed files with 31 additions and 8 deletions

View file

@ -102,7 +102,7 @@ export const Parse = {
throw MismatchError("NaN", val);
},
instanceOf<T>(classDef: { new (): T }): (val: unknown) => T {
instanceOf<T>(classDef: { new(): T }): (val: unknown) => T {
return (val: unknown) => {
if (val instanceof classDef) {
return val;
@ -149,11 +149,7 @@ export const Parse = {
const result = {} as { [K in keyof T]: ReturnType<T[K]> };
for (const key in parsers) {
if (!(key in val)) {
throw new ParseError(`Missing prop: ${key}`, shapeName);
}
const value = (val as Record<string, unknown>)[key];
const value = (val as Record<string, unknown>)[key] ?? undefined;
try {
// biome-ignore lint/style/noNonNullAssertion: Logically guaranteed

View file

@ -140,6 +140,33 @@ describe(Parse.shape, () => {
const shape = { name: Parse.string, age: Parse.number };
expect(() => Parse.shape(shape)(obj)).toThrow(ParseError);
});
test("allows optional object entries", () => {
const parseThing = Parse.shape({
name: Parse.string,
another: Parse.optional(Parse.string),
});
const result = parseThing({
name: "hello",
});
expect(result).toEqual({
name: "hello",
another: undefined,
});
});
test("throws when a required value is missing", () => {
const parseThing = Parse.shape({
name: Parse.string,
another: Parse.optional(Parse.string),
});
expect(() => {
parseThing({ another: "hello" });
}).toThrow(ParseError);
});
});
describe(Parse.enum, () => {
@ -197,7 +224,7 @@ describe(Parse.nan, () => {
});
});
class TestClass {}
class TestClass { }
describe(Parse.instanceOf, () => {
test("Parses instances of a class", () => {
@ -214,7 +241,7 @@ describe(Parse.instanceOf, () => {
test("Throws an error when parsing an instance of a different class", () => {
const testClass = new TestClass();
expect(() => Parse.instanceOf(class AnotherClass {})(testClass)).toThrow(
expect(() => Parse.instanceOf(class AnotherClass { })(testClass)).toThrow(
ParseError,
);
});