text: "use strict";
  // Copyright (c) Microsoft Corporation.
  // Licensed under the MIT License.
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.assert = exports.tests = exports.UndefinedError = void 0;
  /* eslint-disable @typescript-eslint/no-explicit-any */
  /* eslint-disable @typescript-eslint/ban-types */
  const assertExt_1 = require("./assertExt");
  // Formats error messages for assertion failures
  const formatPathAndMessage = (path, message) => `\`${path.join('.')}\` ${message}`;
  /**
   * An error that indicates that the source of the error was an undefined value
   */
  class UndefinedError extends Error {
  }
  exports.UndefinedError = UndefinedError;
  /**
   * Asserts `cond` to the typescript compiler
   *
   * @param {any} cond a condition to assert
   * @param {string[]} path the accumulated path for the assertion
   * @param {string} message an error message to use
   * @param {NewableError} errorCtor an optional error constructor
   */
  function condition(cond, path, message, errorCtor = TypeError) {
      assertExt_1.assertCondition(cond, formatPathAndMessage(path, message), errorCtor);
  }
  /**
   * Construct an assertion function
   *
   * @template T the type to assert
   * @param {string} typeName the name of type `T`
   * @param {Test<T>} test a method to test if an unknown value is of type `T`
   * @param {boolean} acceptNil true if null or undefined values are acceptable
   * @returns {Assertion<T>} an assertion that asserts an unknown value is of type `T`
   */
  function makeAssertion(typeName, test, acceptNil = false) {
      return (val, path) => {
          if (!acceptNil) {
              condition(!isNil(val), path, 'must be defined', UndefinedError);
          }
          condition(test(val), path, `must be of type "${typeName}"`);
      };
  }
  /**
   * Constructs a type assertion that is enforced if the value is not null or undefined
   *
   * @template T the type to assert
   * @param {Assertion<T>} assertion the assertion
   * @returns {Assertion<Maybe<T>>} an assertion that asserts an unknown value is of type `T` or `Nil`
   */
  function makeMaybeAssertion(assertion) {
      return (val, path) => {
          if (!isNil(val)) {
              assertion(val, path);
          }
      };
  }
  /**
   * Takes an assertion for type `T` and returns an assertion for type `Partial<T>`. The implementation
   * expects that the assertion throws `UndefinedError` if an expected value is undefined. All the assertions
   * exported by this package satisfy that requirement.
   *
   * @template T a type extending from `Dictionary`
   * @param {Assertion<T>} assertion an assertion that asserts an unknown value is of type `T`
   * @returns {Assertion<Partial<T>>} an assertion that asserts an unknown value is of type `Partial<T>`
   */
  function makePartialAssertion(assertion) {
      return (val, path) => {
          try {
              assertion(val, path);
          }
          catch (err) {
              if (!isUndefinedError(err)) {
                  throw err;
              }
          }
      };
  }
  /**
   * Test if `val` is of type `any`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `any`
   */
  function isAny(val) {
      return true;
  }
  /**
   * Assert that `val` is of type `any`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function any(val, path) {
      const assertion = makeAssertion('any', isAny);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `any`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeAny(val, path) {
      const assertion = makeMaybeAssertion(any);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `array`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `array`
   */
  function isArray(val) {
      return Array.isArray(val);
  }
  /**
   * Assert that `val` is of type `array`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function array(val, path) {
      const assertion = makeAssertion('array', isArray);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `array`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeArray(val, path) {
      const assertion = makeMaybeAssertion(array);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `boolean`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `boolean`
   */
  function isBoolean(val) {
      return typeof val === 'boolean';
  }
  /**
   * Assert that `val` is of type `boolean`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function boolean(val, path) {
      const assertion = makeAssertion('boolean', isBoolean);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `boolean`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeBoolean(val, path) {
      const assertion = makeMaybeAssertion(boolean);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `Date`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `Date`
   */
  function isDate(val) {
      return val instanceof Date;
  }
  /**
   * Assert that `val` is of type `Date`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function date(val, path) {
      const assertion = makeAssertion('Date', isDate);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `Date`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeDate(val, path) {
      const assertion = makeMaybeAssertion(date);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `Dictionary`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `Dictionary`
   */
  function isDictionary(val) {
      return isObject(val);
  }
  /**
   * Assert that `val` is of type `Dictionary`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function dictionary(val, path) {
      const assertion = makeAssertion('Dictionary', isDictionary);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `Dictionary`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeDictionary(val, path) {
      const assertion = makeMaybeAssertion(dictionary);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `Error`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `Error`
   */
  function isError(val) {
      return val instanceof Error;
  }
  /**
   * Assert that `val` is of type `Error`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function error(val, path) {
      const assertion = makeAssertion('Error', isError);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `TypeError`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `TypeError`
   */
  function isTypeError(val) {
      return val instanceof TypeError;
  }
  /**
   * Assert that `val` is of type `TypeError`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function typeError(val, path) {
      const assertion = makeAssertion('TypeError', isTypeError);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `UndefinedError`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `UndefinedError`
   */
  function isUndefinedError(val) {
      return val instanceof UndefinedError;
  }
  /**
   * Assert that `val` is of type `UndefinedError`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function undefinedError(val, path) {
      const assertion = makeAssertion('UndefinedError', isUndefinedError);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `Func`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `Func`
   */
  function isFunc(val) {
      return typeof val === 'function';
  }
  /**
   * Assert that `val` is of type `Func`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function func(val, path) {
      const assertion = makeAssertion('Function', isFunc);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `Func`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeFunc(val, path) {
      const assertion = makeMaybeAssertion(func);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `Nil`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `Func`
   */
  function isNil(val) {
      return val == null;
  }
  /**
   * Assert that `val` is of type `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function nil(val, path) {
      const assertion = makeAssertion('nil', isNil, true);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `string`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `string`
   */
  function isString(val) {
      return typeof val === 'string';
  }
  /**
   * Assert that `val` is of type `string`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function string(val, path) {
      const assertion = makeAssertion('string', isString);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `string`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeString(val, path) {
      const assertion = makeMaybeAssertion(string);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `number`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `number`
   */
  function isNumber(val) {
      return typeof val === 'number' && !isNaN(val);
  }
  /**
   * Assert that `val` is of type `number`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function number(val, path) {
      const assertion = makeAssertion('number', isNumber);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `number`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeNumber(val, path) {
      const assertion = makeMaybeAssertion(number);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `object`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `object`
   */
  function isObject(val) {
      return !isNil(val) && typeof val === 'object' && !isArray(val);
  }
  /**
   * Assert that `val` is of type `object`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function object(val, path) {
      const assertion = makeAssertion('object', isObject);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `object`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeObject(val, path) {
      const assertion = makeMaybeAssertion(object);
      assertion(val, path);
  }
  /**
   * Test if `val` is of type `unknown`.
   *
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `unknown`
   */
  function isUnknown(val) {
      return true;
  }
  /**
   * Assert that `val` is of type `unknown`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function unknown(val, path) {
      const assertion = makeAssertion('unknown', isUnknown);
      assertion(val, path);
  }
  /**
   * Assert that `val` is of type `unknown`, or `Nil`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function maybeUnknown(val, path) {
      const assertion = makeMaybeAssertion(unknown);
      assertion(val, path);
  }
  /**
   * Make a type test function out of an assertion
   *
   * @template T the type to test
   * @param {Assertion<T>} assertion an assertion
   * @returns {Test<T>} a type test that returns true if an unknown value is of type `T`
   */
  function makeTest(assertion) {
      return (val) => {
          try {
              assertion(val, []);
              return true;
          }
          catch (_err) {
              return false;
          }
      };
  }
  /**
   * **UNSAFE**
   * Test if `val` is of type `object`.
   * This test does not actually verify that `val` is of type `T`. It is useful as the first
   * line in a nested assertion so that remaining assertion calls can leverage helpful intellisense.
   * This method is only exported under the `unsafe` keyword as a constant reminder of this fact.
   *
   * @template T the type to cast `val` to, should extend `Dictionary<unknown>`, i.e. be itself an object
   * @param {any} val value to test
   * @returns {boolean} true if `val` is of type `object`
   */
  function isObjectAs(val) {
      castObjectAs(val, []);
      return isObject(val);
  }
  exports.tests = {
      isAny,
      isArray,
      isBoolean,
      isDate,
      isDictionary,
      isFunc,
      isNil,
      isNumber,
      isObject,
      isString,
      isUnknown,
      isError,
      isTypeError,
      isUndefinedError,
      fromAssertion: makeTest,
      toAssertion: makeAssertion,
      unsafe: { isObjectAs },
  };
  /**
   * Construct an assertion that an unknown value is an array with items of type `T`
   *
   * @template T the item type
   * @param {Assertion<T>} assertion the assertion
   * @returns {Assertion<Array<T>>} an assertion that asserts an unknown value is an array with items of type `T`
   */
  function arrayOf(assertion) {
      return (val, path) => {
          const assertArray = array;
          assertArray(val, path);
          val.forEach((val, idx) => assertion(val, path.concat(`[${idx}]`)));
      };
  }
  /**
   * Assert that `val` is of type `string[]`.
   *
   * @param {any} val value to assert
   * @param {string[]} path path to val (useful for nested assertions)
   */
  function arrayOfString(val, path) {
      const assertion = arrayOf(string);
      assertion(val, path);
  }
  /**
   * Construct an assertion that an unknown value is an array with items of type `T`, or `Nil`
   *
   * @template T the item type
   * @param {Assertion<T>} assertion the assertion
   * @returns {Assertion<Maybe<Array<T>>>} an assertion that asserts an unknown value is an array with
   * items of type `T`, or `Nil`
   */
  function maybeArrayOf(assertion) {
      return (val, path) => {
          const assertArrayOf = arrayOf(assertion);
          const assertMaybeArrayOf = makeMaybeAssertion(assertArrayOf);
          assertMaybeArrayOf(val, path);
      };
  }
  /**
   * Construct an assertion that an unknown value is an instance of type `T`
   *
   * @template T the instance type
   * @param {string} typeName the name of type `T`
   * @param {Newable<T> | Extends<T>} ctor a constructor reference for type `T`
   * @returns {Assertion<T>} an assertion that asserts an unknown value is an instance of type `T`
   */
  function instanceOf(typeName, ctor) {
      return (val, path) => {
          condition(!isNil(val), path, 'must be defined', UndefinedError);
          condition(val instanceof ctor, path, `must be an instance of "${typeName}"`);
      };
  }
  /**
   * Construct an assertion that an unknown value is an instance of type `T`, or `Nil`
   *
   * @template T the instance type
   * @param {string} typeName the name of type `T`
   * @param {Newable<T> | Extends<T>} ctor a constructor reference for type `T`
   * @returns {Assertion<Maybe<T>>} an assertion that asserts an unknown value is an instance of type `T`, or `Nil`
   */
  function maybeInstanceOf(typeName, ctor) {
      return (val, path) => {
          const assertInstanceOf = instanceOf(typeName, ctor);
          const assertMaybeInstanceOf = makeMaybeAssertion(assertInstanceOf);
          assertMaybeInstanceOf(val, path);
      };
  }
  /**
   * Construct an assertion that an unknown value is of type `T`, likely a union type
   *
   * @template T the type, likely a union of other types
   * @param {Array<Test<T>>} tests a set of tests for type `T`
   * @returns {Assertion<T>} an assertion that asserts an unknown value is of type `T`
   */
  function oneOf(...tests) {
      return (val, path) => {
          condition(!isNil(val), path, 'must be defined', UndefinedError);
          if (!tests.some((test) => test(val))) {
              condition(false, path, 'is of wrong type');
          }
      };
  }
  /**
   * Construct an assertion that an unknown value is of type `T`, likely a union type, or `Nil`
   *
   * @template T the type, likely a union of other types
   * @param {Array<Test<T>>} tests a set of tests for type `T`
   * @returns {Assertion<Maybe<T>>} an assertion that asserts an unknown value is of type `T`, or `Nil`
   */
  function maybeOneOf(...tests) {
      return (val, path) => {
          const assertOneOf = oneOf(...tests);
          const assertMaybeOneOf = makeMaybeAssertion(assertOneOf);
          assertMaybeOneOf(val, path);
      };
  }
  /**
   * **UNSAFE**
   * This assertion does not actually verify that `val` is of type `T`. It is useful as the first
   * line in a nested assertion so that remaining assertion calls can leverage helpful intellisense.
   * This method is only exported under the `unsafe` keyword as a constant reminder of this fact.
   *
   * @template T the type to cast `val` to, should extend `Dictionary<unknown>`, i.e. be itself an object
   * @param {any} val the unknown value
   * @param {string[]} path the accumulated assertion path
   */
  function castObjectAs(val, path) {
      const assertWithCast = object;
      assertWithCast(val, path);
  }
  exports.assert = {
      condition,
      any,
      maybeAny,
      array,
      maybeArray,
      boolean,
      maybeBoolean,
      date,
      maybeDate,
      dictionary,
      maybeDictionary,
      error,
      undefinedError,
      typeError,
      func,
      maybeFunc,
      nil,
      number,
      maybeNumber,
      object,
      maybeObject,
      string,
      maybeString,
      unknown,
      maybeUnknown,
      arrayOf,
      maybeArrayOf,
      arrayOfString,
      instanceOf,
      maybeInstanceOf,
      oneOf,
      maybeOneOf,
      // Some helpful, well, helpers
      fromTest: makeAssertion,
      makeMaybe: makeMaybeAssertion,
      makePartial: makePartialAssertion,
      toTest: makeTest,
      unsafe: { castObjectAs },
  };
  //# sourceMappingURL=types.js.map