diff --git a/typescript/option/src/helpers/withDefaultLazy.test.ts b/typescript/option/src/helpers/withDefaultLazy.test.ts new file mode 100644 index 0000000..5ec7d97 --- /dev/null +++ b/typescript/option/src/helpers/withDefaultLazy.test.ts @@ -0,0 +1,50 @@ +import { expect } from 'chai' +import { withDefaultLazy } from './withDefaultLazy' +import { None, Some } from '../types' +import { alwaysX, x, someX } from '../../test/constants' +import { constantly } from '@thi.ng/compose' +import { spy } from 'sinon' + +describe('The withDefaultLazy helper', () => { + describe('When given None', () => { + it('should return the default when given None', () => { + // act + const result = withDefaultLazy(alwaysX, None) + + // assert + expect(result).to.equal(x) + }) + + it('should call the lazy default', () => { + // arrange + const func = spy(constantly(x)) + + // act + withDefaultLazy(func, None) + + // assert + expect(func.called).to.be.true + }) + }) + + describe('When given Some', () => { + it('should return the inner value', () => { + // act + const result = withDefaultLazy(constantly(0), Some(1)) + + // assert + expect(result).to.equal(1) + }) + + it('should not call the lazy default', () => { + // arrange + const func = spy(constantly(x)) + + // act + withDefaultLazy(func, someX) + + // assert + expect(func.called).to.be.false + }) + }) +}) diff --git a/typescript/option/src/helpers/withDefaultLazy.ts b/typescript/option/src/helpers/withDefaultLazy.ts new file mode 100644 index 0000000..da46a15 --- /dev/null +++ b/typescript/option/src/helpers/withDefaultLazy.ts @@ -0,0 +1,16 @@ +import { Option } from '../types' +import { isSome } from './isSome' +import { Lazy } from '../internalTypes' +import { get } from './get' + +/** + * Same as withDefault but the default is only evaluated when the option is None. + * + * @param _default Function returning the default value to use. + * @param option The option to get the default of. + */ +export const withDefaultLazy = (_default: Lazy, option: Option) => { + if (isSome(option)) { + return get(option) + } else return _default() +} diff --git a/typescript/option/src/internalTypes.ts b/typescript/option/src/internalTypes.ts index 339d971..bbe0938 100644 --- a/typescript/option/src/internalTypes.ts +++ b/typescript/option/src/internalTypes.ts @@ -6,3 +6,4 @@ export type Predicate = (v: T) => boolean export type Folder = (s: U, v: T) => U export type BackFolder = (v: T, s: U) => U export type Nullable = T | null +export type Lazy = () => T diff --git a/typescript/option/test/constants.ts b/typescript/option/test/constants.ts index e6f1b1b..31bd9c5 100644 --- a/typescript/option/test/constants.ts +++ b/typescript/option/test/constants.ts @@ -7,4 +7,5 @@ export const x = Symbol('x') // same as x but for some export const someX = Some(x) +export const alwaysX = constantly(x) export const alwaysSomeX = constantly(someX)