Home Manual Reference Source Repository

all/@jali-ms/util/src/argument-verifiers.js

import * as TypeGuards from './type-guards';
import ArgumentEmptyStringError from './argument-empty-string-error';
import ArgumentError from './argument-error';
import ArgumentFalseError from './argument-false-error';
import ArgumentFalsyError from './argument-falsy-error';
import ArgumentNanError from './argument-nan-error';
import ArgumentNullError from './argument-null-error';
import ArgumentTypeError from './argument-type-error';
import ArgumentUndefinedError from './argument-undefined-error';
import ArgumentWhitespaceStringError from './argument-whitespace-string-error';
import ArgumentZeroError from './argument-zero-error';
/**
 * Throws an error if the specified argument value does not pass the specified test.
 *
 * @param T -
 *    The `value` type. **Note:** This is a TypeScript type parameter, not a parameter of the
 *    function.
 * @param {!string} name -
 *    The formal parameter name.
 * @param {T} value -
 *    The function argument.
 * @param {!function(value: T) => boolean} test -
 *    Evaluates whether the value meets expectations.
 * @param {(string | function(value: string): string)} [message] -
 *    Optional custom message or message factory.
 *
 * @throws {ArgumentError}
 *    The test failed.
 *
 * @example <caption>verify that parameter deposit is non-negative</caption>
 * verifyArgument('deposit', deposit, arg => arg > 0.0);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code>, examples ④ & ⑤</a>
 * @see {@link ArgumentError}
 * @see {@link verifyDefined}
 * @see {@link verifyTruthy}
 * @since 0.0.1
 */
export function verifyArgument(name, value, test, message) {
    if (!test(value)) {
        throw new ArgumentError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument is not an `Array`.
 *
 * > **Note:** Calls {@link Array.isArray}.
 *
 * @param T -
 *    The `element` type. **Note:** This is a TypeScript type parameter, not a parameter of the
 *    function.
 * @param {!string} name -
 *    The formal parameter name.
 * @param {T} value -
 *    The function argument.
 * @param {(string | function(value: string): string)} [message] -
 *    Optional custom message or message factory.
 *
 * @throws {ArgumentUndefinedError}
 *    The argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    The argument is not an `Array`.
 *
 * @example <caption>verify that parameter collection is an Array</caption>
 * verifyArray('collection', collection);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link isIterable}
 * @see {@link verifyIterable}
 * @since 0.0.1
 */
export function verifyArray(name, value, message) {
    verifyDefined(name, value, message);
    if (!Array.isArray(value)) {
        throw new ArgumentTypeError('Array', name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument is not strictly a boolean value.
 *
 * > **Note:** If you want to test for _truthy_ values, use {@link verifyTruthy}.
 *
 * @param {!string} name -
 *    The formal parameter name.
 * @param {boolean} value -
 *    The function argument.
 * @param {(string | function(value: string): string)} [message] -
 *    Optional custom message or message factory.
 *
 * @throws {ArgumentUndefinedError}
 *    The argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    The argument is not `boolean`.
 *
 * @example <caption>verify that parameter isValid is boolean</caption>
 * verifyBoolean('isValid', isValid);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentUndefinedError}
 * @see {@link verifyDefined}
 * @see {@link verifyTruthy}
 * @since 0.0.1
 */
export function verifyBoolean(name, value, message) {
    verifyDefined(name, value, message);
    if (typeof value !== 'boolean') {
        throw new ArgumentTypeError('boolean', name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument is `undefined`.
 *
 * > **Note:** If you want to test for _truthy_ values, use {@link verifyTruthy}.
 *
 * @param T -
 *    The `value` type. **Note:** This is a TypeScript type parameter, not a parameter of the
 *    function.
 * @param {!string} name -
 *    The formal parameter name.
 * @param {T} value -
 *    The function argument.
 * @param {(string | function(value: string): string)} [message] -
 *    Optional custom message or message factory.
 *
 * @throws {ArgumentUndefinedError}
 *    The argument is `undefined`.
 *
 * @example <caption>verify that parameter element is defined</caption>
 * verifyDefined('element', element);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link verifyTruthy}
 * @since 0.0.1
 */
export function verifyDefined(name, value, message) {
    if (value === undefined) {
        throw new ArgumentUndefinedError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument is not strictly a function expression.
 *
 * > **Note:** If you want to test for _truthy_ values, use {@link verifyTruthy}.
 *
 * @param {!string} name -
 *    The formal parameter name.
 * @param {Function} value -
 *    The function argument.
 * @param {(string | function(value: string): string)} [message] -
 *    Optional custom message or message factory.
 *
 * @throws {ArgumentUndefinedError}
 *    The argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    The argument is not a `function`.
 *
 * @example <caption>verify that parameter factory is a function</caption>
 * verifyFunction('factory', factory);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentUndefinedError}
 * @see {@link verifyDefined}
 * @see {@link verifyTruthy}
 * @since 0.0.1
 */
export function verifyFunction(name, value, message) {
    verifyDefined(name, value, message);
    if (typeof value !== 'function') {
        throw new ArgumentTypeError('function', name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument does not support iteration.
 *
 * > **Note:** Calls {@link isIterable} to determine iterability.
 *
 * @param T -
 *    The `element` type. **Note:** This is a TypeScript type parameter, not a parameter of the
 *    function.
 * @param {!string} name -
 *    The formal parameter name.
 * @param {T} value -
 *    The function argument.
 * @param {(string | function(value: string): string)} [message] -
 *    Optional custom message or message factory.
 *
 * @throws {ArgumentUndefinedError}
 *    The argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    The argument does not support iteration.
 *
 * @example <caption>verify that parameter collection is iterable</caption>
 * verifyIterable('collection', collection);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link isIterable}
 * @see {@link verifyArray}
 * @since 0.0.1
 */
export function verifyIterable(name, value, message) {
    verifyDefined(name, value, message);
    if (!TypeGuards.isIterable(value)) {
        throw new ArgumentTypeError('iterable', name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not a non-empty string.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {string} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `string`.
 * @throws {ArgumentEmptyStringError}
 *    the argument is an empty `string`.
 *
 * @example <caption>verify that parameter firstName is a non-empty string</caption>
 * verifyNonEmpty('firstName', firstName);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code>, example ②</a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentEmptyStringError}
 * @see {@link verifyDefined}
 * @see {@link verifyString}
 * @see {@link verifyNotWhitespace}
 * @since 0.0.1
 */
export function verifyNonEmpty(name, value, message) {
    verifyString(name, value, message);
    if (value === '') {
        throw new ArgumentEmptyStringError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not a non-zero number.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {number} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `number`.
 * @throws {ArgumentNanError}
 *    the argument is `NaN`.
 * @throws {ArgumentZeroError}
 *    the argument is a number the value zero.
 *
 * @example <caption>verify that parameter height has a nonzero value</caption>
 * verifyNonEmpty('height', height);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentNanError}
 * @see {@link ArgumentZeroError}
 * @see {@link verifyDefined}
 * @see {@link verifyNumber}
 * @since 0.0.1
 */
export function verifyNonZero(name, value, message) {
    verifyNumber(name, value, message);
    if (value === 0) {
        throw new ArgumentZeroError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is `undefined` or `null`.
 *
 * > **Note:** Consider using {@link verifyTruthy} or {@link verifyObject}.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {number} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `number`.
 * @throws {ArgumentNanError}
 *    the argument is `NaN`.
 * @throws {ArgumentZeroError}
 *    the argument is a number the value zero.
 *
 * @example <caption>verify that parameter height has a nonzero value</caption>
 * verifyNonEmpty('height', height);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code>, example ①</a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentNanError}
 * @see {@link ArgumentZeroError}
 * @see {@link verifyDefined}
 * @see {@link verifyNumber}
 * @since 0.0.1
 */
export function verifyNotNull(name, value, message) {
    verifyDefined(name, value, message);
    if (value === null) {
        throw new ArgumentNullError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument is not a string with non whitespace characters.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {string} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `string`.
 * @throws {ArgumentEmptyStringError}
 *    the argument is an empty `string`.
 * @throws {ArgumentWhitespaceStringError}
 *    the argument has only whitespace characters.
 *
 * @example <caption>verify that parameter firstName has non-whitespace characters</caption>
 * verifyNotWhitespace('firstName', firstName);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code>, example ②</a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentEmptyStringError}
 * @see {@link ArgumentWhitespaceStringError}
 * @see {@link verifyDefined}
 * @see {@link verifyString}
 * @see {@link verifyNonEmpty}
 * @since 0.0.1
 */
export function verifyNotWhitespace(name, value, message) {
    verifyNonEmpty(name, value, message);
    if (value.trim() === '') {
        throw new ArgumentWhitespaceStringError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not a `number` or has a value of `NaN`.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {number} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `number`.
 * @throws {ArgumentNanError}
 *    the argument is `NaN`.
 * @throws {ArgumentZeroError}
 *    the argument is a number the value zero.
 *
 * @example <caption>verify that parameter price is a number</caption>
 * verifyNumber('price', price);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentNanError}
 * @see {@link ArgumentZeroError}
 * @see {@link verifyDefined}
 * @see {@link verifyNonZero}
 * @since 0.0.1
 */
export function verifyNumber(name, value, message) {
    verifyDefined(name, value, message);
    if (typeof value !== 'number') {
        throw new ArgumentTypeError('number', name, errorMessage(value, message));
    }
    if (Number.isNaN(value)) {
        throw new ArgumentNanError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not an `Object`.
 *
 * > **Note:** To exclude `null` values also call {@link verifyNotNull}
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {Object} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not an `Object`.
 *
 * @example <caption>verify that parameter height has a nonzero value</caption>
 * verifyNonEmpty('height', height);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentNanError}
 * @see {@link ArgumentZeroError}
 * @see {@link verifyDefined}
 * @see {@link verifyNonZero}
 * @since 0.0.1
 */
export function verifyObject(name, value, message) {
    verifyDefined(name, value, message);
    if (typeof value !== 'object') {
        throw new ArgumentTypeError('object', name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not a `string`.
 *
 * > **Note:** To verify a meaningful value consider using {@link verifyNonEmpty} or
 * > {@link verifyNotWhitespace}.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {string} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `string`.
 *
 * @example <caption>verify that parameter alphabet is a string</caption>
 * verifyNonEmpty('alphabet', alphabet);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link verifyDefined}
 * @see {@link verifyNonEmpty}
 * @see {@link verifyNotWhitespace}
 * @since 0.0.1
 */
export function verifyString(name, value, message) {
    verifyDefined(name, value, message);
    if (typeof value !== 'string') {
        throw new ArgumentTypeError('string', name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not a boolean with the value 'true'.
 *
 * > **Note:** To verify a _truthy_ value, use {@link verifyTruthy}.
 *
 * @param {string} name -
 *    the formal parameter name
 * @param {boolean} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined`.
 * @throws {ArgumentTypeError}
 *    the argument is not a `boolean`.
 * @throws {ArgumentFalseError}
 *    the argument is a number the value zero.
 *
 * @example <caption>verify that parameter isValid is true</caption>
 * verifyNonEmpty('isValid', isValid);
 *
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code></a>
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentTypeError}
 * @see {@link ArgumentFalseError}
 * @see {@link verifyDefined}
 * @see {@link verifyBoolean}
 * @see {@link verifyTruthy}
 * @since 0.0.1
 */
export function verifyTrue(name, value, message) {
    verifyBoolean(name, value, message);
    if (value === false) {
        throw new ArgumentFalseError(name, errorMessage(value, message));
    }
}
/**
 * Throws an error if the specified argument value is not _truthy_.
 *
 * The `loose` parameter changes what exception is thrown. If `loose`, then only
 * {@link ArgumentFalsyError} is thrown. Otherwise, the exception for the appropriate _falsy_ value
 * is thrown.
 *
 * > **Note:** You can test for any of the _falsy_ values individually using the appropriate
 * > `verify...` function.
 *
 * @param T -
 *    The `value` type. **Note:** This is a TypeScript type parameter, not a parameter of the
 *    function.
 * @param {string} name -
 *    the formal parameter name
 * @param {T} value -
 *    the function argument
 * @param {?(string | function(value: string): string)} message -
 *    optional custom message or message factory
 *
 * @throws {ArgumentFalsyError}
 *    the argument is _falsy_ and `loose` is specified.
 * @throws {ArgumentEmptyStringError}
 *    the argument is an empty `string` and `loose` is not specified.
 * @throws {ArgumentFalseError}
 *    the argument has the value `false` and `loose` is not specified.
 * @throws {ArgumentNanError}
 *    the argument has the value `NaN` and `loose` is not specified.
 * @throws {ArgumentNullError}
 *    the argument has the value `null` and `loose` is not specified.
 * @throws {ArgumentUndefinedError}
 *    the argument is `undefined` and `loose` is not specified.
 * @throws {ArgumentUndefinedError}
 *    the argument is zero and `loose` is not specified.
 *
 * @example <caption>verify that parameter item is truthy</caption>
 * verifyTruthy('item', item);
 *
 * @see <a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy" target="_blank">
 *    Definition of falsy</a> (MDN)
 * @see <a href="manual/overview.html#package-jali-ms-util">
 *    package <code>@jali-ms/util</code></a>
 * @see <a href="manual/overview.html#module-jali-ms-util-errors">
 *    module <code>@jali-ms/util/errors</code></a>
 * @see <a href="manual/example.html#jali_ms_util_errors">
 *    Example method <code>jali_ms_util_errors</code>, example ③</a>
 * @see {@link ArgumentEmptyStringError}
 * @see {@link ArgumentFalseError}
 * @see {@link ArgumentNanError}
 * @see {@link ArgumentNullError}
 * @see {@link ArgumentUndefinedError}
 * @see {@link ArgumentZeroError}
 * @see {@link verifyDefined}
 * @see {@link verifyNonEmpty}
 * @see {@link verifyNonZero}
 * @see {@link verifyNotNull}
 * @see {@link verifyNumber}
 * @see {@link verifyTrue}
 * @since 0.0.1
 */
export function verifyTruthy(name, value, loose = false, message) {
    if (!value) {
        if (loose) {
            throw new ArgumentFalsyError(name, errorMessage(value, message));
        }
        verifyNotNull(name, value, message); // Also checks for defined.
        if (typeof value === 'boolean') {
            verifyTrue(name, value, errorMessage(value, message));
        }
        else if (typeof value === 'string') {
            verifyNonEmpty(name, value, errorMessage(value, message));
        }
        else if (typeof value === 'number') {
            // Also checks for not NaN
            verifyNonZero(name, value, errorMessage(value, message));
        }
    }
}
function errorMessage(value, message) {
    return (typeof message === 'function') ? message(value) : message;
}