Allow optional shape entries
This commit is contained in:
parent
5ce10bed57
commit
26db320717
2 changed files with 31 additions and 8 deletions
|
@ -102,7 +102,7 @@ export const Parse = {
|
||||||
throw MismatchError("NaN", val);
|
throw MismatchError("NaN", val);
|
||||||
},
|
},
|
||||||
|
|
||||||
instanceOf<T>(classDef: { new (): T }): (val: unknown) => T {
|
instanceOf<T>(classDef: { new(): T }): (val: unknown) => T {
|
||||||
return (val: unknown) => {
|
return (val: unknown) => {
|
||||||
if (val instanceof classDef) {
|
if (val instanceof classDef) {
|
||||||
return val;
|
return val;
|
||||||
|
@ -149,11 +149,7 @@ export const Parse = {
|
||||||
const result = {} as { [K in keyof T]: ReturnType<T[K]> };
|
const result = {} as { [K in keyof T]: ReturnType<T[K]> };
|
||||||
|
|
||||||
for (const key in parsers) {
|
for (const key in parsers) {
|
||||||
if (!(key in val)) {
|
const value = (val as Record<string, unknown>)[key] ?? undefined;
|
||||||
throw new ParseError(`Missing prop: ${key}`, shapeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = (val as Record<string, unknown>)[key];
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// biome-ignore lint/style/noNonNullAssertion: Logically guaranteed
|
// biome-ignore lint/style/noNonNullAssertion: Logically guaranteed
|
||||||
|
|
|
@ -140,6 +140,33 @@ describe(Parse.shape, () => {
|
||||||
const shape = { name: Parse.string, age: Parse.number };
|
const shape = { name: Parse.string, age: Parse.number };
|
||||||
expect(() => Parse.shape(shape)(obj)).toThrow(ParseError);
|
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, () => {
|
describe(Parse.enum, () => {
|
||||||
|
@ -197,7 +224,7 @@ describe(Parse.nan, () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
class TestClass {}
|
class TestClass { }
|
||||||
|
|
||||||
describe(Parse.instanceOf, () => {
|
describe(Parse.instanceOf, () => {
|
||||||
test("Parses instances of a class", () => {
|
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", () => {
|
test("Throws an error when parsing an instance of a different class", () => {
|
||||||
const testClass = new TestClass();
|
const testClass = new TestClass();
|
||||||
expect(() => Parse.instanceOf(class AnotherClass {})(testClass)).toThrow(
|
expect(() => Parse.instanceOf(class AnotherClass { })(testClass)).toThrow(
|
||||||
ParseError,
|
ParseError,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue