Skip to content

Commit

Permalink
feat(Option): add isNoneOr (#824)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranet authored Nov 2, 2024
1 parent 143375f commit bb6c889
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
27 changes: 27 additions & 0 deletions packages/result/src/lib/Option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,33 @@ export class Option<T, Exists extends boolean = boolean> {
return !this[ExistsProperty];
}

/**
* Returns `true` if the option is a `None` value or the value inside of it matches a predicate.
*
* @example
* ```typescript
* const x: Option<number> = some(2);
* assert.equal(x.isNoneOr((x) => x > 1), true);
* ```
* @example
* ```typescript
* const x: Option<number> = some(0);
* assert.equal(x.isNoneOr((x) => x > 1), false);
* ```
* @example
* ```typescript
* const x: Option<number> = none;
* assert.equal(x.isNoneOr((x) => x > 1), true);
* ```
*
* @see {@link https://doc.rust-lang.org/std/option/enum.Option.html#method.is_none_or}
*/
public isNoneOr<R extends T>(cb: (value: T) => value is R): this is None | Some<R>;
public isNoneOr<R extends boolean>(cb: (value: T) => R): If<Exists, R, true>;
public isNoneOr<R extends boolean>(cb: (value: T) => R): If<Exists, R, true> {
return this.match({ some: (value) => cb(value), none: () => true });
}

/**
* Returns the contained `Some` value.
* @param message The message for the error.
Expand Down
30 changes: 30 additions & 0 deletions packages/result/tests/Option.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,36 @@ describe('Option', () => {
});
});

describe('isNoneOr', () => {
test('GIVEN some AND true-returning callback THEN returns true', () => {
const x = some(2);
const cb = vi.fn((value: number) => value > 1);

expect(x.isNoneOr(cb)).toBe(true);
expect(cb).toHaveBeenCalledTimes(1);
expect(cb).toHaveBeenCalledWith(2);
expect(cb).toHaveLastReturnedWith(true);
});

test('GIVEN some AND false-returning callback THEN returns false', () => {
const x = some(0);
const cb = vi.fn((value: number) => value > 1);

expect(x.isNoneOr(cb)).toBe(false);
expect(cb).toHaveBeenCalledTimes(1);
expect(cb).toHaveBeenCalledWith(0);
expect(cb).toHaveLastReturnedWith(false);
});

test('GIVEN none THEN always returns false', () => {
const x = none;
const cb = vi.fn((value: number) => value > 1);

expect(x.isNoneOr(cb)).toBe(true);
expect(cb).not.toHaveBeenCalled();
});
});

describe('expect', () => {
test('GIVEN ok THEN returns value', () => {
const x = some(2);
Expand Down

0 comments on commit bb6c889

Please sign in to comment.