-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#develop custom result implementation
- Loading branch information
1 parent
4e3d11a
commit 8138857
Showing
10 changed files
with
181 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'feature-fetch': patch | ||
'@blgc/utils': patch | ||
--- | ||
|
||
Custom and very barebone Result implementation to not bloat bundle |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
|
||
import { Err, Ok, unwrapErr, unwrapOk, type TResult } from './result'; | ||
|
||
describe('Result implementation', () => { | ||
it('should create an Ok result correctly', () => { | ||
const result = Ok(42); | ||
expect(result._type).toBe('Ok'); | ||
expect(result.value).toBe(42); | ||
expect(result.unwrap()).toBe(42); | ||
expect(result.isOk()).toBe(true); | ||
expect(result.isErr()).toBe(false); | ||
}); | ||
|
||
it('should create an Err result correctly', () => { | ||
const result = Err('Some error'); | ||
expect(result._type).toBe('Err'); | ||
expect(result.error).toBe('Some error'); | ||
expect(() => result.unwrap()).toThrowError(); | ||
expect(result.isOk()).toBe(false); | ||
expect(result.isErr()).toBe(true); | ||
}); | ||
|
||
it('should handle unwrap correctly for Ok result', () => { | ||
const result = Ok('Success'); | ||
expect(result.unwrap()).toBe('Success'); | ||
}); | ||
|
||
it('should throw error on unwrap for Err result', () => { | ||
const result = Err('Error occurred'); | ||
expect(() => result.unwrap()).toThrow('Error occurred'); | ||
}); | ||
|
||
it('should distinguish between Ok and Err using type guards', () => { | ||
const okResult: TResult<number, string> = Ok(99); | ||
const errResult: TResult<number, string> = Err('Failure'); | ||
|
||
if (okResult.isOk()) { | ||
expect(okResult.value).toBe(99); | ||
} else { | ||
throw new Error('Expected okResult to be Ok'); | ||
} | ||
|
||
if (errResult.isErr()) { | ||
expect(errResult.error).toBe('Failure'); | ||
} else { | ||
throw new Error('Expected errResult to be Err'); | ||
} | ||
}); | ||
|
||
it('should handle multiple Ok and Err instances', () => { | ||
const okResult1 = Ok(1); | ||
const okResult2 = Ok(2); | ||
const errResult1 = Err('First error'); | ||
const errResult2 = Err('Second error'); | ||
|
||
expect(okResult1.isOk()).toBe(true); | ||
expect(okResult2.isOk()).toBe(true); | ||
expect(errResult1.isErr()).toBe(true); | ||
expect(errResult2.isErr()).toBe(true); | ||
}); | ||
|
||
it('should handle unwrapOk correctly for Ok result', () => { | ||
const result = Ok('Success'); | ||
expect(unwrapOk(result)).toBe('Success'); | ||
}); | ||
|
||
it('should throw error on unwrapErr for Ok result', () => { | ||
const result = Ok('No error'); | ||
expect(() => unwrapErr(result)).toThrow('Expected an Err result'); | ||
}); | ||
|
||
it('should handle unwrapErr correctly for Err result', () => { | ||
const result = Err('Error occurred'); | ||
expect(unwrapErr(result)).toBe('Error occurred'); | ||
}); | ||
|
||
it('should throw error on unwrapOk for Err result', () => { | ||
const result = Err('Error occurred'); | ||
expect(() => unwrapOk(result)).toThrow('Expected an Ok result'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
export type TResultError = string | Error; | ||
|
||
export interface TOkResult<T, E extends TResultError> { | ||
_type: 'Ok'; | ||
value: T; | ||
unwrap: () => T; | ||
isOk: () => this is TOkResult<T, E>; | ||
isErr: () => this is TErrResult<T, E>; | ||
} | ||
|
||
export interface TErrResult<T, E extends TResultError> { | ||
_type: 'Err'; | ||
error: E; | ||
unwrap: () => T; | ||
isOk: () => this is TOkResult<T, E>; | ||
isErr: () => this is TErrResult<T, E>; | ||
} | ||
|
||
export type TResult<T, E extends TResultError> = TOkResult<T, E> | TErrResult<T, E>; | ||
|
||
// Factory function for creating an Ok result | ||
export function Ok<T, E extends TResultError>(value: T): TOkResult<T, E> { | ||
return { | ||
_type: 'Ok', | ||
value, | ||
unwrap() { | ||
return value; | ||
}, | ||
// @ts-expect-error -- Assignable | ||
isOk() { | ||
return true; | ||
}, | ||
// @ts-expect-error -- Assignable | ||
isErr() { | ||
return false; | ||
} | ||
}; | ||
} | ||
|
||
// Factory function for creating an Err result | ||
export function Err<T, E extends TResultError>(error: E): TErrResult<T, E> { | ||
return { | ||
_type: 'Err', | ||
error, | ||
unwrap() { | ||
if (error instanceof Error) { | ||
throw error; | ||
} else { | ||
throw new Error(error); | ||
} | ||
}, | ||
// @ts-expect-error -- Assignable | ||
isOk() { | ||
return false; | ||
}, | ||
// @ts-expect-error -- Assignable | ||
isErr() { | ||
return true; | ||
} | ||
}; | ||
} | ||
|
||
// Extracts value from an Ok result or throws an error if it's an Err | ||
export function unwrapOk<T, E extends TResultError>(result: TResult<T, E>): T { | ||
if (result.isOk()) { | ||
return result.value; | ||
} | ||
throw new Error('Expected an Ok result'); | ||
} | ||
|
||
// Extracts error from an Err result or throws an error if it's an Ok | ||
export function unwrapErr<T, E extends TResultError>(result: TResult<T, E>): E { | ||
if (result.isErr()) { | ||
return result.error; | ||
} | ||
throw new Error('Expected an Err result'); | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.