From 907b9c1325f6e1145a8b31e6e35171a8e77291df Mon Sep 17 00:00:00 2001 From: StyleShit Date: Sat, 13 Jul 2024 23:18:06 +0300 Subject: [PATCH] feat: add safe parsing support --- .changeset/curvy-laws-provide.md | 5 +++++ src/__tests__/index.test.ts | 21 +++++++++++++++++++++ src/schemas/schema.ts | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 .changeset/curvy-laws-provide.md diff --git a/.changeset/curvy-laws-provide.md b/.changeset/curvy-laws-provide.md new file mode 100644 index 0000000..f6e624a --- /dev/null +++ b/.changeset/curvy-laws-provide.md @@ -0,0 +1,5 @@ +--- +'bodek': patch +--- + +Add safe parsing support diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index af99c41..bd49e38 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -148,4 +148,25 @@ describe('Bodek', () => { expect(() => schema.parse(-2)).toThrow('Number must be positive'); expect(() => schema.parse(3)).toThrow('Number must be even'); }); + + it('should support safe parsing', () => { + // Arrange. + const schema = b.number(); + + // Assert - valid. + expect(schema.safeParse(123)).toEqual({ + success: true, + data: 123, + }); + + // Assert - invalid. + expect(schema.safeParse('hello')).toEqual({ + success: false, + error: new Error('hello is not a number'), + }); + + expectTypeOf(schema.safeParse(123)).toEqualTypeOf< + { success: true; data: number } | { success: false; error: Error } + >(); + }); }); diff --git a/src/schemas/schema.ts b/src/schemas/schema.ts index 34e16a8..65c6341 100644 --- a/src/schemas/schema.ts +++ b/src/schemas/schema.ts @@ -4,6 +4,10 @@ type RefineParams = { message?: string; }; +type SafeParseResult = + | { success: true; data: T } + | { success: false; error: Error }; + export abstract class Schema { private refinements: Array<{ validator: RefineValidator; @@ -26,6 +30,22 @@ export abstract class Schema { return parsed; } + safeParse(value: unknown, message?: string): SafeParseResult { + try { + const data = this.parse(value, message); + + return { + success: true, + data, + }; + } catch (error) { + return { + success: false, + error: error as Error, + }; + } + } + refine(validator: RefineValidator, params?: RefineParams) { this.refinements.push({ validator,