// Type definitions for Lo-Dash
// Project: http://lodash.com/
// Definitions by: Brian Zengel <https://github.com/bczengel>
// Definitions: https://github.com/borisyankov/DefinitelyTyped

declare var lodash: _.LoDashStatic;

declare module _ {
    interface LoDashStatic {
        /**
        * Creates a lodash object which wraps the given value to enable intuitive method chaining.
        *
        * In addition to Lo-Dash methods, wrappers also have the following Array methods:
        * concat, join, pop, push, reverse, shift, slice, sort, splice, and unshift
        *
        * Chaining is supported in custom builds as long as the value method is implicitly or
        * explicitly included in the build.
        *
        * The chainable wrapper functions are:
        * after, assign, bind, bindAll, bindKey, chain, compact, compose, concat, countBy,
        * createCallback, curry, debounce, defaults, defer, delay, difference, filter, flatten,
        * forEach, forEachRight, forIn, forInRight, forOwn, forOwnRight, functions, groupBy,
        * indexBy, initial, intersection, invert, invoke, keys, map, max, memoize, merge, min,
        * object, omit, once, pairs, partial, partialRight, pick, pluck, pull, push, range, reject,
        * remove, rest, reverse, shuffle, slice, sort, sortBy, splice, tap, throttle, times,
        * toArray, transform, union, uniq, unshift, unzip, values, where, without, wrap, and zip
        *
        * The non-chainable wrapper functions are:
        * clone, cloneDeep, contains, escape, every, find, findIndex, findKey, findLast,
        * findLastIndex, findLastKey, has, identity, indexOf, isArguments, isArray, isBoolean,
        * isDate, isElement, isEmpty, isEqual, isFinite, isFunction, isNaN, isNull, isNumber,
        * isObject, isPlainObject, isRegExp, isString, isUndefined, join, lastIndexOf, mixin,
        * noConflict, parseInt, pop, random, reduce, reduceRight, result, shift, size, some,
        * sortedIndex, runInContext, template, unescape, uniqueId, and value
        *
        * The wrapper functions first and last return wrapped values when n is provided, otherwise
        * they return unwrapped values.
        *
        * Explicit chaining can be enabled by using the _.chain method.
        **/
        (value: number): LoDashWrapper<number>;
        (value: string): LoDashWrapper<string>;
        (value: boolean): LoDashWrapper<boolean>;
        <T>(value: Array<T>): LoDashArrayWrapper<T>;
        <T extends {}>(value: T): LoDashObjectWrapper<T>;
        (value: any): LoDashWrapper<any>;

        /**
        * The semantic version number.
        **/
        VERSION: string;

        /**
        * An object used to flag environments features.
        **/
        support: Support;

        /**
        * By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby
        * (ERB). Change the following template settings to use alternative delimiters.
        **/
        templateSettings: TemplateSettings;
    }

    /**
    * By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby
    * (ERB). Change the following template settings to use alternative delimiters.
    **/
    interface TemplateSettings {
        /**
        * The "escape" delimiter.
        **/
        escape?: RegExp;

        /**
        * The "evaluate" delimiter.
        **/
        evaluate?: RegExp;

        /**
        * An object to import into the template as local variables.
        **/
        imports?: Dictionary<any>;

        /**
        * The "interpolate" delimiter.
        **/
        interpolate?: RegExp;

        /**
        * Used to reference the data object in the template text.
        **/
        variable?: string;
    }

    /**
    * An object used to flag environments features.
    **/
    interface Support {
        /**
        * Detect if an arguments object’s [[Class]] is resolvable (all but Firefox < 4, IE < 9).
        **/
        argsClass: boolean;

        /**
        * Detect if arguments objects are Object objects (all but Narwhal and Opera < 10.5).
        **/
        argsObject: boolean;

        /**
        * Detect if name or message properties of Error.prototype are enumerable by default.
        * (IE < 9, Safari < 5.1)
        **/
        enumErrorProps: boolean;

        /**
        * Detect if Function#bind exists and is inferred to be fast (all but V8).
        **/
        fastBind: boolean;

        /**
        * Detect if functions can be decompiled by Function#toString (all but PS3 and older Opera
        * mobile browsers & avoided in Windows 8 apps).
        **/
        funcDecomp: boolean;

        /**
        * Detect if Function#name is supported (all but IE).
        **/
        funcNames: boolean;

        /**
        * Detect if arguments object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS,
        * Safari < 5.1).
        **/
        nonEnumArgs: boolean;

        /**
        * Detect if properties shadowing those on Object.prototype are non-enumerable.
        *
        * In IE < 9 an objects own properties, shadowing non-enumerable ones, are made
        * non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).
        **/
        nonEnumShadows: boolean;

        /**
        * Detect if own properties are iterated after inherited properties (all but IE < 9).
        **/
        ownLast: boolean;

        /**
        * Detect if Array#shift and Array#splice augment array-like objects correctly.
        *
        * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array shift() and splice()
        * functions that fail to remove the last element, value[0], of array-like objects even
        * though the length property is set to 0. The shift() method is buggy in IE 8 compatibility
        * mode, while splice() is buggy regardless of mode in IE < 9 and buggy in compatibility mode
        * in IE 9.
        **/
        spliceObjects: boolean;

        /**
        * Detect lack of support for accessing string characters by index.
        *
        * IE < 8 can't access characters by index and IE 8 can only access characters by index on
        * string literals.
        **/
        unindexedChars: boolean;
    }

    interface LoDashWrapperBase<T, TWrapper> {
        /**
        * Produces the toString result of the wrapped value.
        * @return Returns the string result.
        **/
        toString(): string;

        /**
        * Extracts the wrapped value.
        * @return The wrapped value.
        **/
        valueOf(): T;

        /**
        * @see valueOf
        **/
        value(): T;
    }

    interface LoDashWrapper<T> extends LoDashWrapperBase<T, LoDashWrapper<T>> { }

    interface LoDashObjectWrapper<T> extends LoDashWrapperBase<T, LoDashObjectWrapper<T>> { }

    interface LoDashArrayWrapper<T> extends LoDashWrapperBase<T[], LoDashArrayWrapper<T>> {
        concat(...items: T[]): LoDashArrayWrapper<T>;
        join(seperator?: string): LoDashWrapper<string>;
        pop(): LoDashWrapper<T>;
        push(...items: T[]): void;
        reverse(): LoDashArrayWrapper<T>;
        shift(): LoDashWrapper<T>;
        slice(start: number, end?: number): LoDashArrayWrapper<T>;
        sort(compareFn?: (a: T, b: T) => number): LoDashArrayWrapper<T>;
        splice(start: number): LoDashArrayWrapper<T>;
        splice(start: number, deleteCount: number, ...items: any[]): LoDashArrayWrapper<T>;
        unshift(...items: any[]): LoDashWrapper<number>;
    }

    //_.chain
    interface LoDashStatic {
        /**
        * Creates a lodash object that wraps the given value with explicit method chaining enabled.
        * @param value The value to wrap.
        * @return The wrapper object.
        **/
        chain(value: number): LoDashWrapper<number>;
        chain(value: string): LoDashWrapper<string>;
        chain(value: boolean): LoDashWrapper<boolean>;
        chain<T>(value: Array<T>): LoDashArrayWrapper<T>;
        chain<T extends {}>(value: T): LoDashObjectWrapper<T>;
        chain(value: any): LoDashWrapper<any>;
    }

    interface LoDashWrapperBase<T, TWrapper> {
        /**
        * Enables explicit method chaining on the wrapper object.
        * @see _.chain
        * @return The wrapper object.
        **/
        chain(): TWrapper;
    }

    //_.tap
    interface LoDashStatic {
        /**
        * Invokes interceptor with the value as the first argument and then returns value. The
        * purpose of this method is to "tap into" a method chain in order to perform operations on
        * intermediate results within the chain.
        * @param value The value to provide to interceptor
        * @param interceptor The function to invoke.
        * @return value
        **/
        tap<T>(
            value: T,
            interceptor: (value: T) => void): T;
    }

    interface LoDashWrapperBase<T, TWrapper> {
        /**
        * @see _.tap
        **/
        tap(interceptor: (value: T) => void): TWrapper;
    }

    /*********
    * Arrays *
    **********/

    //_.compact
    interface LoDashStatic {
        /**
        * Returns a copy of the array with all falsy values removed. In JavaScript, false, null, 0, "",
        * undefined and NaN are all falsy.
        * @param array Array to compact.
        * @return (Array) Returns a new array of filtered values.
        **/
        compact<T>(array: Array<T>): T[];

        /**
        * @see _.compact
        **/
        compact<T>(array: List<T>): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.compact
        **/
        compact(): LoDashArrayWrapper<T>;
    }

    //_.difference
    interface LoDashStatic {
        /**
        * Creates an array excluding all values of the provided arrays using strict equality for comparisons
        * , i.e. ===.
        * @param array The array to process
        * @param others The arrays of values to exclude.
        * @return Returns a new array of filtered values.
        **/
        difference<T>(
            array: Array<T>,
            ...others: Array<T>[]): T[];
        /**
        * @see _.difference
        **/
        difference<T>(
            array: List<T>,
            ...others: List<T>[]): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.difference
        **/
        difference(
            ...others: Array<T>[]): LoDashArrayWrapper<T>;
        /**
        * @see _.difference
        **/
        difference(
            ...others: List<T>[]): LoDashArrayWrapper<T>;
    }

    //_.findIndex
    interface LoDashStatic {
        /**
        * This method is like _.find except that it returns the index of the first element that passes
        * the callback check, instead of the element itself.
        * @param array The array to search.
        * @param {(Function|Object|string)} callback The function called per iteration. If a property name or object is provided it will be
        * used to create a ".pluck" or ".where" style callback, respectively.
        * @param thisArg The this binding of callback.
        * @return Returns the index of the found element, else -1.
        **/
        findIndex<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): number;

        /**
        * @see _.findIndex
        **/
        findIndex<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): number;

        /**
        * @see _.findIndex
        **/
        findIndex<T>(
            array: Array<T>,
            pluckValue: string): number;

        /**
        * @see _.findIndex
        **/
        findIndex<T>(
            array: List<T>,
            pluckValue: string): number;

        /**
        * @see _.findIndex
        **/
        findIndex<W, T>(
            array: Array<T>,
            whereDictionary: W): number;

        /**
        * @see _.findIndex
        **/
        findIndex<W, T>(
            array: List<T>,
            whereDictionary: W): number;
    }

    //_.findLastIndex
    interface LoDashStatic {
        /**
        * This method is like _.findIndex except that it iterates over elements of a collection from right to left.
        * @param array The array to search.
        * @param {(Function|Object|string)} callback The function called per iteration. If a property name or object is provided it will be
        * used to create a ".pluck" or ".where" style callback, respectively.
        * @param thisArg The this binding of callback.
        * @return Returns the index of the found element, else -1.
        **/
        findLastIndex<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): number;

        /**
        * @see _.findLastIndex
        **/
        findLastIndex<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): number;

        /**
        * @see _.findLastIndex
        **/
        findLastIndex<T>(
            array: Array<T>,
            pluckValue: string): number;

        /**
        * @see _.findLastIndex
        **/
        findLastIndex<T>(
            array: List<T>,
            pluckValue: string): number;

        /**
        * @see _.findLastIndex
        **/
        findLastIndex<T>(
            array: Array<T>,
            whereDictionary: Dictionary<any>): number;

        /**
        * @see _.findLastIndex
        **/
        findLastIndex<T>(
            array: List<T>,
            whereDictionary: Dictionary<any>): number;
    }

    //_.first
    interface LoDashStatic {
        /**
        * Gets the first element or first n elements of an array. If a callback is provided
        * elements at the beginning of the array are returned as long as the callback returns
        * truey. The callback is bound to thisArg and invoked with three arguments; (value,
        * index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback
        * will return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return ]
        * true for elements that have the properties of the given object, else false.
        * @param array Retrieves the first element of this array.
        * @return Returns the first element of `array`.
        **/
        first<T>(array: Array<T>): T;

        /**
        * @see _.first
        **/
        first<T>(array: List<T>): T;

        /**
        * @see _.first
        * @param n The number of elements to return.
        **/
        first<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.first
        * @param n The number of elements to return.
        **/
        first<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.first
        * @param callback The function called per element.
        * @param [thisArg] The this binding of callback.
        **/
        first<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.first
        * @param callback The function called per element.
        * @param [thisArg] The this binding of callback.
        **/
        first<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.first
        * @param pluckValue "_.pluck" style callback value
        **/
        first<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.first
        * @param pluckValue "_.pluck" style callback value
        **/
        first<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.first
        * @param whereValue "_.where" style callback value
        **/
        first<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.first
        * @param whereValue "_.where" style callback value
        **/
        first<W, T>(
            array: List<T>,
            whereValue: W): T[];

        /**
        * @see _.first
        **/
        head<T>(array: Array<T>): T;

        /**
        * @see _.first
        **/
        head<T>(array: List<T>): T;

        /**
        * @see _.first
        **/
        head<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.first
        **/
        head<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.first
        **/
        head<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.first
        **/
        head<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.first
        **/
        head<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.first
        **/
        head<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.first
        **/
        head<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.first
        **/
        head<W, T>(
            array: List<T>,
            whereValue: W): T[];

        /**
        * @see _.first
        **/
        take<T>(array: Array<T>): T;

        /**
        * @see _.first
        **/
        take<T>(array: List<T>): T;

        /**
        * @see _.first
        **/
        take<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.first
        **/
        take<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.first
        **/
        take<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.first
        **/
        take<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.first
        **/
        take<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.first
        **/
        take<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.first
        **/
        take<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.first
        **/
        take<W, T>(
            array: List<T>,
            whereValue: W): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.first
        **/
        first(): T;

        /**
        * @see _.first
        * @param n The number of elements to return.
        **/
        first(n: number): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param callback The function called per element.
        * @param [thisArg] The this binding of callback.
        **/
        first(
            callback: ListIterator<T, boolean>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param pluckValue "_.pluck" style callback value
        **/
        first(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param whereValue "_.where" style callback value
        **/
        first<W>(whereValue: W): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        **/
        head(): T;

        /**
        * @see _.first
        * @param n The number of elements to return.
        **/
        head(n: number): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param callback The function called per element.
        * @param [thisArg] The this binding of callback.
        **/
        head(
            callback: ListIterator<T, boolean>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param pluckValue "_.pluck" style callback value
        **/
        head(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param whereValue "_.where" style callback value
        **/
        head<W>(whereValue: W): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        **/
        take(): T;

        /**
        * @see _.first
        * @param n The number of elements to return.
        **/
        take(n: number): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param callback The function called per element.
        * @param [thisArg] The this binding of callback.
        **/
        take(
            callback: ListIterator<T, boolean>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param pluckValue "_.pluck" style callback value
        **/
        take(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.first
        * @param whereValue "_.where" style callback value
        **/
        take<W>(whereValue: W): LoDashArrayWrapper<T>;
    }

    //_.flatten
    interface LoDashStatic {
        /**
        * Flattens a nested array (the nesting can be to any depth). If isShallow is truey, the
        * array will only be flattened a single level. If a callback is provided each element of
        * the array is passed through the callback before flattening. The callback is bound to
        * thisArg and invoked with three arguments; (value, index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param array The array to flatten.
        * @param shallow If true then only flatten one level, optional, default = false.
        * @return `array` flattened.
        **/
        flatten<T>(array: Array<any>, isShallow?: boolean): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(array: List<any>, isShallow?: boolean): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: Array<any>,
            isShallow: boolean,
            callback: ListIterator<any, T>,
            thisArg?: any): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: List<any>,
            isShallow: boolean,
            callback: ListIterator<any, T>,
            thisArg?: any): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: Array<any>,
            callback: ListIterator<any, T>,
            thisArg?: any): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: List<any>,
            callback: ListIterator<any, T>,
            thisArg?: any): T[];

        /**
        * @see _.flatten
        **/
        flatten<W, T>(
            array: Array<any>,
            isShallow: boolean,
            whereValue: W): T[];

        /**
        * @see _.flatten
        **/
        flatten<W, T>(
            array: List<any>,
            isShallow: boolean,
            whereValue: W): T[];

        /**
        * @see _.flatten
        **/
        flatten<W, T>(
            array: Array<any>,
            whereValue: W): T[];

        /**
        * @see _.flatten
        **/
        flatten<W, T>(
            array: List<any>,
            whereValue: W): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: Array<any>,
            isShallow: boolean,
            pluckValue: string): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: List<any>,
            isShallow: boolean,
            pluckValue: string): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: Array<any>,
            pluckValue: string): T[];

        /**
        * @see _.flatten
        **/
        flatten<T>(
            array: List<any>,
            pluckValue: string): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.flatten
        **/
        flatten<Flat>(isShallow?: boolean): LoDashArrayWrapper<Flat>;

        /**
        * @see _.flatten
        **/
        flatten<Flat>(
            isShallow: boolean,
            callback: ListIterator<T, Flat>,
            thisArg?: any): LoDashArrayWrapper<Flat>;

        /**
        * @see _.flatten
        **/
        flatten<Flat>(
            callback: ListIterator<T, Flat>,
            thisArg?: any): LoDashArrayWrapper<Flat>;

        /**
        * @see _.flatten
        **/
        flatten<Flat>(
            isShallow: boolean,
            pluckValue: string): LoDashArrayWrapper<Flat>;

        /**
        * @see _.flatten
        **/
        flatten<Flat>(
            pluckValue: string): LoDashArrayWrapper<Flat>;

        /**
        * @see _.flatten
        **/
        flatten<Flat, W>(
            isShallow: boolean,
            whereValue: W): LoDashArrayWrapper<Flat>;

        /**
        * @see _.flatten
        **/
        flatten<Flat, W>(
            whereValue: W): LoDashArrayWrapper<Flat>;
    }

    //_.indexOf
    interface LoDashStatic {
        /**
        * Gets the index at which the first occurrence of value is found using strict equality
        * for comparisons, i.e. ===. If the array is already sorted providing true for fromIndex
        * will run a faster binary search.
        * @param array The array to search.
        * @param value The value to search for.
        * @param fromIndex The index to search from.
        * @return The index of `value` within `array`.
        **/
        indexOf<T>(
            array: Array<T>,
            value: T): number;

        /**
        * @see _.indexOf
        **/
        indexOf<T>(
            array: List<T>,
            value: T): number;

        /**
        * @see _.indexOf
        * @param fromIndex The index to search from
        **/
        indexOf<T>(
            array: Array<T>,
            value: T,
            fromIndex: number): number;

        /**
        * @see _.indexOf
        * @param fromIndex The index to search from
        **/
        indexOf<T>(
            array: List<T>,
            value: T,
            fromIndex: number): number;

        /**
        * @see _.indexOf
        * @param isSorted True to perform a binary search on a sorted array.
        **/
        indexOf<T>(
            array: Array<T>,
            value: T,
            isSorted: boolean): number;

        /**
        * @see _.indexOf
        * @param isSorted True to perform a binary search on a sorted array.
        **/
        indexOf<T>(
            array: List<T>,
            value: T,
            isSorted: boolean): number;
    }

    //_.initial
    interface LoDashStatic {
        /**
        * Gets all but the last element or last n elements of an array. If a callback is provided
        * elements at the end of the array are excluded from the result as long as the callback
        * returns truey. The callback is bound to thisArg and invoked with three arguments;
        * (value, index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param array The array to query.
        * @param n Leaves this many elements behind, optional.
        * @return Returns everything but the last `n` elements of `array`.
        **/
        initial<T>(
            array: Array<T>): T[];

        /**
        * @see _.initial
        **/
        initial<T>(
            array: List<T>): T[];

        /**
        * @see _.initial
        * @param n The number of elements to exclude.
        **/
        initial<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.initial
        * @param n The number of elements to exclude.
        **/
        initial<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.initial
        * @param callback The function called per element
        **/
        initial<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>): T[];

        /**
        * @see _.initial
        * @param callback The function called per element
        **/
        initial<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>): T[];

        /**
        * @see _.initial
        * @param pluckValue _.pluck style callback
        **/
        initial<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.initial
        * @param pluckValue _.pluck style callback
        **/
        initial<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.initial
        * @param whereValue _.where style callback
        **/
        initial<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.initial
        * @param whereValue _.where style callback
        **/
        initial<W, T>(
            array: List<T>,
            whereValue: W): T[];
    }

    //_.intersection
    interface LoDashStatic {
        /**
        * Creates an array of unique values present in all provided arrays using strict
        * equality for comparisons, i.e. ===.
        * @param arrays The arrays to inspect.
        * @return Returns an array of composite values.
        **/
        intersection<T>(...arrays: Array<T>[]): T[];

        /**
        * @see _.intersection
        **/
        intersection<T>(...arrays: List<T>[]): T[];
    }

    //_.last
    interface LoDashStatic {
        /**
        * Gets the last element or last n elements of an array. If a callback is provided
        * elements at the end of the array are returned as long as the callback returns truey.
        * The callback is bound to thisArg and invoked with three arguments; (value, index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param array The array to query.
        * @return Returns the last element(s) of array.
        **/
        last<T>(array: Array<T>): T;

        /**
        * @see _.last
        **/
        last<T>(array: List<T>): T;

        /**
        * @see _.last
        * @param n The number of elements to return
        **/
        last<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.last
        * @param n The number of elements to return
        **/
        last<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.last
        * @param callback The function called per element
        **/
        last<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.last
        * @param callback The function called per element
        **/
        last<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.last
        * @param pluckValue _.pluck style callback
        **/
        last<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.last
        * @param pluckValue _.pluck style callback
        **/
        last<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.last
        * @param whereValue _.where style callback
        **/
        last<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.last
        * @param whereValue _.where style callback
        **/
        last<W, T>(
            array: List<T>,
            whereValue: W): T[];
    }

    //_.lastIndexOf
    interface LoDashStatic {
        /**
        * Gets the index at which the last occurrence of value is found using strict equality
        * for comparisons, i.e. ===. If fromIndex is negative, it is used as the offset from the
        * end of the collection.
        * @param array The array to search.
        * @param value The value to search for.
        * @param fromIndex The index to search from.
        * @return The index of the matched value or -1.
        **/
        lastIndexOf<T>(
            array: Array<T>,
            value: T,
            fromIndex?: number): number;

        /**
        * @see _.lastIndexOf
        **/
        lastIndexOf<T>(
            array: List<T>,
            value: T,
            fromIndex?: number): number;
    }

    //_.pull
    interface LoDashStatic {
        /**
        * Removes all provided values from the given array using strict equality for comparisons,
        * i.e. ===.
        * @param array The array to modify.
        * @param values The values to remove.
        * @return array.
        **/
        pull(
            array: Array<any>,
            ...values: any[]): any[];

        /**
        * @see _.pull
        **/
        pull(
            array: List<any>,
            ...values: any[]): any[];
    }

    //_.range
    interface LoDashStatic {
        /**
        * Creates an array of numbers (positive and/or negative) progressing from start up
        * to but not including end. If start is less than stop a zero-length range is created
        * unless a negative step is specified.
        * @param start The start of the range.
        * @param end The end of the range.
        * @param step The value to increment or decrement by.
        * @return Returns a new range array.
        **/
        range(
            start: number,
            stop: number,
            step?: number): number[];

        /**
        * @see _.range
        * @param end The end of the range.
        * @return Returns a new range array.
        * @note If start is not specified the implementation will never pull the step (step = arguments[2] || 0)
        **/
        range(stop: number): number[];
    }

    //_.remove
    interface LoDashStatic {
        /**
        * Removes all elements from an array that the callback returns truey for and returns
        * an array of removed elements. The callback is bound to thisArg and invoked with three
        * arguments; (value, index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param array The array to modify.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return A new array of removed elements.
        **/
        remove(
            array: Array<any>,
            callback?: ListIterator<any, boolean>,
            thisArg?: any): any[];

        /**
        * @see _.remove
        **/
        remove(
            array: List<any>,
            callback?: ListIterator<any, boolean>,
            thisArg?: any): any[];

        /**
        * @see _.remove
        * @param pluckValue _.pluck style callback
        **/
        remove(
            array: Array<any>,
            pluckValue?: string): any[];

        /**
        * @see _.remove
        * @param pluckValue _.pluck style callback
        **/
        remove(
            array: List<any>,
            pluckValue?: string): any[];

        /**
        * @see _.remove
        * @param whereValue _.where style callback
        **/
        remove(
            array: Array<any>,
            wherealue?: Dictionary<any>): any[];

        /**
        * @see _.remove
        * @param whereValue _.where style callback
        **/
        remove(
            array: List<any>,
            wherealue?: Dictionary<any>): any[];
    }

    //_.rest
    interface LoDashStatic {
        /**
        * The opposite of _.initial this method gets all but the first element or first n elements of
        * an array. If a callback function is provided elements at the beginning of the array are excluded
        * from the result as long as the callback returns truey. The callback is bound to thisArg and
        * invoked with three arguments; (value, index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will return
        * the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return true
        * for elements that have the properties of the given object, else false.
        * @param array The array to query.
        * @param {(Function|Object|number|string)} [callback=1] The function called per element or the number
        * of elements to exclude. If a property name or object is provided it will be used to create a
        * ".pluck" or ".where" style callback, respectively.
        * @param {*} [thisArg] The this binding of callback.
        * @return Returns a slice of array.
        **/
        rest<T>(array: Array<T>): T[];

        /**
        * @see _.rest
        **/
        rest<T>(array: List<T>): T[];

        /**
        * @see _.rest
        **/
        rest<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.rest
        **/
        rest<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.rest
        **/
        rest<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.rest
        **/
        rest<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.rest
        **/
        rest<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.rest
        **/
        rest<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.rest
        **/
        rest<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.rest
        **/
        rest<W, T>(
            array: List<T>,
            whereValue: W): T[];

        /**
        * @see _.rest
        **/
        drop<T>(array: Array<T>): T[];

        /**
        * @see _.rest
        **/
        drop<T>(array: List<T>): T[];

        /**
        * @see _.rest
        **/
        drop<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.rest
        **/
        drop<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.rest
        **/
        drop<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.rest
        **/
        drop<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.rest
        **/
        drop<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.rest
        **/
        drop<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.rest
        **/
        drop<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.rest
        **/
        drop<W, T>(
            array: List<T>,
            whereValue: W): T[];

        /**
        * @see _.rest
        **/
        tail<T>(array: Array<T>): T[];

        /**
        * @see _.rest
        **/
        tail<T>(array: List<T>): T[];

        /**
        * @see _.rest
        **/
        tail<T>(
            array: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.rest
        **/
        tail<T>(
            array: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.rest
        **/
        tail<T>(
            array: Array<T>,
            n: number): T[];

        /**
        * @see _.rest
        **/
        tail<T>(
            array: List<T>,
            n: number): T[];

        /**
        * @see _.rest
        **/
        tail<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.rest
        **/
        tail<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.rest
        **/
        tail<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.rest
        **/
        tail<W, T>(
            array: List<T>,
            whereValue: W): T[];
    }

    //_.sortedIndex
    interface LoDashStatic {
        /**
        * Uses a binary search to determine the smallest index at which a value should be inserted
        * into a given sorted array in order to maintain the sort order of the array. If a callback
        * is provided it will be executed for value and each element of array to compute their sort
        * ranking. The callback is bound to thisArg and invoked with one argument; (value).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param array The sorted list.
        * @param value The value to determine its index within `list`.
        * @param callback Iterator to compute the sort ranking of each value, optional.
        * @return The index at which value should be inserted into array.
        **/
        sortedIndex<T, TSort>(
            array: Array<T>,
            value: T,
            callback?: (x: T) => TSort,
            thisArg?: any): number;

        /**
        * @see _.sortedIndex
        **/
        sortedIndex<T, TSort>(
            array: List<T>,
            value: T,
            callback?: (x: T) => TSort,
            thisArg?: any): number;

        /**
        * @see _.sortedIndex
        * @param pluckValue the _.pluck style callback
        **/
        sortedIndex<T>(
            array: Array<T>,
            value: T,
            pluckValue: string): number;

        /**
        * @see _.sortedIndex
        * @param pluckValue the _.pluck style callback
        **/
        sortedIndex<T>(
            array: List<T>,
            value: T,
            pluckValue: string): number;

        /**
        * @see _.sortedIndex
        * @param pluckValue the _.where style callback
        **/
        sortedIndex<W, T>(
            array: Array<T>,
            value: T,
            whereValue: W): number;

        /**
        * @see _.sortedIndex
        * @param pluckValue the _.where style callback
        **/
        sortedIndex<W, T>(
            array: List<T>,
            value: T,
            whereValue: W): number;
    }

    //_.union
    interface LoDashStatic {
        /**
        * Creates an array of unique values, in order, of the provided arrays using strict
        * equality for comparisons, i.e. ===.
        * @param arrays The arrays to inspect.
        * @return Returns an array of composite values.
        **/
        union<T>(...arrays: Array<T>[]): T[];

        /**
        * @see _.union
        **/
        union<T>(...arrays: List<T>[]): T[];
    }

    //_.uniq
    interface LoDashStatic {
        /**
        * Creates a duplicate-value-free version of an array using strict equality for comparisons,
        * i.e. ===. If the array is sorted, providing true for isSorted will use a faster algorithm.
        * If a callback is provided each element of array is passed through the callback before
        * uniqueness is computed. The callback is bound to thisArg and invoked with three arguments;
        * (value, index, array).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param array Array to remove duplicates from.
        * @param isSorted True if `array` is already sorted, optiona, default = false.
        * @param iterator Transform the elements of `array` before comparisons for uniqueness.
        * @param context 'this' object in `iterator`, optional.
        * @return Copy of `array` where all elements are unique.
        **/
        uniq<T, TSort>(array: Array<T>, isSorted?: boolean): T[];

        /**
        * @see _.uniq
        **/
        uniq<T, TSort>(array: List<T>, isSorted?: boolean): T[];

        /**
        * @see _.uniq
        **/
        uniq<T, TSort>(
            array: Array<T>,
            isSorted: boolean,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        **/
        uniq<T, TSort>(
            array: List<T>,
            isSorted: boolean,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        **/
        uniq<T, TSort>(
            array: Array<T>,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        **/
        uniq<T, TSort>(
            array: List<T>,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        uniq<T>(
            array: Array<T>,
            isSorted: boolean,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        uniq<T>(
            array: List<T>,
            isSorted: boolean,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        uniq<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        uniq<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        uniq<W, T>(
            array: Array<T>,
            isSorted: boolean,
            whereValue: W): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        uniq<W, T>(
            array: List<T>,
            isSorted: boolean,
            whereValue: W): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        uniq<W, T>(
            array: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        uniq<W, T>(
            array: List<T>,
            whereValue: W): T[];

        /**
        * @see _.uniq
        **/
        unique<T>(array: Array<T>, isSorted?: boolean): T[];

        /**
        * @see _.uniq
        **/
        unique<T>(array: List<T>, isSorted?: boolean): T[];

        /**
        * @see _.uniq
        **/
        unique<T, TSort>(
            array: Array<T>,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        **/
        unique<T, TSort>(
            array: List<T>,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        **/
        unique<T, TSort>(
            array: Array<T>,
            isSorted: boolean,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        **/
        unique<T, TSort>(
            array: List<T>,
            isSorted: boolean,
            callback: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        unique<T>(
            array: Array<T>,
            isSorted: boolean,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        unique<T>(
            array: List<T>,
            isSorted: boolean,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        unique<T>(
            array: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        unique<T>(
            array: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        unique<W, T>(
            array: Array<T>,
            whereValue?: W): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        unique<W, T>(
            array: List<T>,
            whereValue?: W): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        unique<W, T>(
            array: Array<T>,
            isSorted: boolean,
            whereValue?: W): T[];

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        unique<W, T>(
            array: List<T>,
            isSorted: boolean,
            whereValue?: W): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.uniq
        **/
        uniq<TSort>(isSorted?: boolean): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        **/
        uniq<TSort>(
            isSorted: boolean,
            callback: ListIterator<T, TSort>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        **/
        uniq<TSort>(
            callback: ListIterator<T, TSort>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        uniq(
            isSorted: boolean,
            pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        uniq(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        uniq<W>(
            isSorted: boolean,
            whereValue: W): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        uniq<W>(
            whereValue: W): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        **/
        unique<TSort>(isSorted?: boolean): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        **/
        unique<TSort>(
            isSorted: boolean,
            callback: ListIterator<T, TSort>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        **/
        unique<TSort>(
            callback: ListIterator<T, TSort>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        unique(
            isSorted: boolean,
            pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param pluckValue _.pluck style callback
        **/
        unique(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        unique<W>(
            isSorted: boolean,
            whereValue: W): LoDashArrayWrapper<T>;

        /**
        * @see _.uniq
        * @param whereValue _.where style callback
        **/
        unique<W>(
            whereValue: W): LoDashArrayWrapper<T>;
    }

    //_.without
    interface LoDashStatic {
        /**
        * Creates an array excluding all provided values using strict equality for comparisons, i.e. ===.
        * @param array The array to filter.
        * @param values The value(s) to exclude.
        * @return A new array of filtered values.
        **/
        without<T>(
            array: Array<T>,
            ...values: T[]): T[];

        /**
        * @see _.without
        **/
        without<T>(
            array: List<T>,
            ...values: T[]): T[];
    }

    //_.xor
    interface LoDashStatic {
        /**
        * Creates an array that is the symmetric difference of the provided arrays.
        * @param array The array to process
        * @param others The arrays of values to calculate the symmetric difference.
        * @return Returns a new array of filtered values.
        **/
        xor<T>(
            array: Array<T>,
            ...others: Array<T>[]): T[];
        /**
        * @see _.xor
        **/
        xor<T>(
            array: List<T>,
            ...others: List<T>[]): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.xor
        **/
        xor(
            ...others: Array<T>[]): LoDashArrayWrapper<T>;
        /**
        * @see _.xor
        **/
        xor(
            ...others: List<T>[]): LoDashArrayWrapper<T>;
    }

    //_.zip
    interface LoDashStatic {
        /**
        * Creates an array of grouped elements, the first of which contains the first
        * elements of the given arrays, the second of which contains the second elements
        * of the given arrays, and so on.
        * @param arrays Arrays to process.
        * @return A new array of grouped elements.
        **/
        zip(...arrays: any[][]): any[][];

        /**
        * @see _.zip
        **/
        zip(...arrays: any[]): any[];

        /**
        * @see _.zip
        **/
        unzip(...arrays: any[][]): any[][];

        /**
        * @see _.zip
        **/
        unzip(...arrays: any[]): any[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.zip
        **/
        zip(...arrays: any[][]): _.LoDashArrayWrapper<any[][]>;

        /**
        * @see _.zip
        **/
        unzip(...arrays: any[]): _.LoDashArrayWrapper<any[][]>;
    }

    //_.zipObject
    interface LoDashStatic {
        /**
        * Creates an object composed from arrays of keys and values. Provide either a single
        * two dimensional array, i.e. [[key1, value1], [key2, value2]] or two arrays, one of
        * keys and one of corresponding values.
        * @param keys The array of keys.
        * @param values The array of values.
        * @return An object composed of the given keys and corresponding values.
        **/
        zipObject<TResult extends {}>(
            keys: List<string>,
            values: List<any>): TResult;

        /**
        * @see _.object
        **/
        object<TResult extends {}>(
            keys: List<string>,
            values: List<any>): TResult;
    }

    /* *************
     * Collections *
     ************* */

    //_.at
    interface LoDashStatic {
        /**
        * Creates an array of elements from the specified indexes, or keys, of the collection.
        * Indexes may be specified as individual arguments or as arrays of indexes.
        * @param collection The collection to iterate over.
        * @param indexes The indexes of collection to retrieve, specified as individual indexes or
        * arrays of indexes.
        * @return A new array of elements corresponding to the provided indexes.
        **/
        at<T>(
            collection: Array<T>,
            indexes: number[]): T[];

        /**
        * @see _.at
        **/
        at<T>(
            collection: List<T>,
            indexes: number[]): T[];

        /**
        * @see _.at
        **/
        at<T>(
            collection: Dictionary<T>,
            indexes: number[]): T[];

        /**
        * @see _.at
        **/
        at<T>(
            collection: Array<T>,
            ...indexes: number[]): T[];

        /**
        * @see _.at
        **/
        at<T>(
            collection: List<T>,
            ...indexes: number[]): T[];

        /**
        * @see _.at
        **/
        at<T>(
            collection: Dictionary<T>,
            ...indexes: number[]): T[];
    }

    //_.contains
    interface LoDashStatic {
        /**
        * Checks if a given value is present in a collection using strict equality for comparisons,
        * i.e. ===. If fromIndex is negative, it is used as the offset from the end of the collection.
        * @param collection The collection to iterate over.
        * @param target The value to check for.
        * @param fromIndex The index to search from.
        * @return True if the target element is found, else false.
        **/
        contains<T>(
            collection: Array<T>,
            target: T,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        **/
        contains<T>(
            collection: List<T>,
            target: T,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        * @param dictionary The dictionary to iterate over.
        * @param key The key in the dictionary to search for.
        **/
        contains<T>(
            dictionary: Dictionary<T>,
            key: string,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        * @param searchString the string to search
        * @param targetString the string to search for
        **/
        contains(
            searchString: string,
            targetString: string,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        **/
        include<T>(
            collection: Array<T>,
            target: T,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        **/
        include<T>(
            collection: List<T>,
            target: T,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        **/
        include<T>(
            dictionary: Dictionary<T>,
            key: string,
            fromIndex?: number): boolean;

        /**
        * @see _.contains
        **/
        include(
            searchString: string,
            targetString: string,
            fromIndex?: number): boolean;
    }

    //_.countBy
    interface LoDashStatic {
        /**
        * Creates an object composed of keys generated from the results of running each element
        * of collection through the callback. The corresponding value of each key is the number
        * of times the key was returned by the callback. The callback is bound to thisArg and
        * invoked with three arguments; (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return Returns the composed aggregate object.
        **/
        countBy<T>(
            collection: Array<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): Dictionary<number>;

        /**
        * @see _.countBy
        * @param callback Function name
        **/
        countBy<T>(
            collection: List<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): Dictionary<number>;

        /**
        * @see _.countBy
        * @param callback Function name
        **/
        countBy<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): Dictionary<number>;

        /**
        * @see _.countBy
        * @param callback Function name
        **/
        countBy<T>(
            collection: Array<T>,
            callback: string,
            thisArg?: any): Dictionary<number>;

        /**
        * @see _.countBy
        * @param callback Function name
        **/
        countBy<T>(
            collection: List<T>,
            callback: string,
            thisArg?: any): Dictionary<number>;

        /**
        * @see _.countBy
        * @param callback Function name
        **/
        countBy<T>(
            collection: Dictionary<T>,
            callback: string,
            thisArg?: any): Dictionary<number>;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.countBy
        **/
        countBy(
            callback?: ListIterator<T, any>,
            thisArg?: any): LoDashObjectWrapper<Dictionary<number>>;

        /**
        * @see _.countBy
        * @param callback Function name
        **/
        countBy(
            callback: string,
            thisArg?: any): LoDashObjectWrapper<Dictionary<number>>;
    }

    //_.every
    interface LoDashStatic {
        /**
        * Checks if the given callback returns truey value for all elements of a collection.
        * The callback is bound to thisArg and invoked with three arguments; (value, index|key,
        * collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return True if all elements passed the callback check, else false.
        **/
        every<T>(
            collection: Array<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        every<T>(
            collection: List<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        every<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        every<T>(
            collection: Array<T>,
            pluckValue: string): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        every<T>(
            collection: List<T>,
            pluckValue: string): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        every<T>(
            collection: Dictionary<T>,
            pluckValue: string): boolean;

        /**
        * @see _.every
        * @param whereValue _.where style callback
        **/
        every<W, T>(
            collection: Array<T>,
            whereValue: W): boolean;

        /**
        * @see _.every
        * @param whereValue _.where style callback
        **/
        every<W, T>(
            collection: List<T>,
            whereValue: W): boolean;

        /**
        * @see _.every
        * @param whereValue _.where style callback
        **/
        every<W, T>(
            collection: Dictionary<T>,
            whereValue: W): boolean;

        /**
        * @see _.every
        **/
        all<T>(
            collection: Array<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.every
        **/
        all<T>(
            collection: List<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.every
        **/
        all<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        all<T>(
            collection: Array<T>,
            pluckValue: string): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        all<T>(
            collection: List<T>,
            pluckValue: string): boolean;

        /**
        * @see _.every
        * @param pluckValue _.pluck style callback
        **/
        all<T>(
            collection: Dictionary<T>,
            pluckValue: string): boolean;

        /**
        * @see _.every
        * @param whereValue _.where style callback
        **/
        all<W, T>(
            collection: Array<T>,
            whereValue: W): boolean;

        /**
        * @see _.every
        * @param whereValue _.where style callback
        **/
        all<W, T>(
            collection: List<T>,
            whereValue: W): boolean;

        /**
        * @see _.every
        * @param whereValue _.where style callback
        **/
        all<W, T>(
            collection: Dictionary<T>,
            whereValue: W): boolean;
    }

    //_.filter
    interface LoDashStatic {
        /**
        * Iterates over elements of a collection, returning an array of all elements the
        * callback returns truey for. The callback is bound to thisArg and invoked with three
        * arguments; (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param context The this binding of callback.
        * @return Returns a new array of elements that passed the callback check.
        **/
        filter<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.filter
        **/
        filter<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.filter
        **/
        filter<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<T>(
            collection: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<T>(
            collection: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<T>(
            collection: Dictionary<T>,
            pluckValue: string): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<W, T>(
            collection: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<W, T>(
            collection: List<T>,
            whereValue: W): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T[];

        /**
        * @see _.filter
        **/
        select<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.filter
        **/
        select<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.filter
        **/
        select<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<T>(
            collection: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<T>(
            collection: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<T>(
            collection: Dictionary<T>,
            pluckValue: string): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<W, T>(
            collection: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<W, T>(
            collection: List<T>,
            whereValue: W): T[];

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.filter
        **/
        filter(
            callback: ListIterator<T, boolean>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter(
            pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        filter<W>(
            whereValue: W): LoDashArrayWrapper<T>;

        /**
        * @see _.filter
        **/
        select(
            callback: ListIterator<T, boolean>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select(
            pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.filter
        * @param pluckValue _.pluck style callback
        **/
        select<W>(
            whereValue: W): LoDashArrayWrapper<T>;
    }

    //_.find
    interface LoDashStatic {
        /**
        * Iterates over elements of a collection, returning the first element that the callback
        * returns truey for. The callback is bound to thisArg and invoked with three arguments;
        * (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param collection Searches for a value in this list.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return The found element, else undefined.
        **/
        find<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        find<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        find<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        find<W, T>(
            collection: Array<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        find<W, T>(
            collection: List<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        find<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        find<T>(
            collection: Array<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        find<T>(
            collection: List<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        find<T>(
            collection: Dictionary<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        **/
        detect<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        detect<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        detect<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        detect<W, T>(
            collection: Array<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        detect<W, T>(
            collection: List<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        detect<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        detect<T>(
            collection: Array<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        detect<T>(
            collection: List<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        detect<T>(
            collection: Dictionary<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        **/
        findWhere<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        findWhere<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        findWhere<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        findWhere<W, T>(
            collection: Array<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        findWhere<W, T>(
            collection: List<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        findWhere<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        findWhere<T>(
            collection: Array<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        findWhere<T>(
            collection: List<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        findWhere<T>(
            collection: Dictionary<T>,
            pluckValue: string): T;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.find
        */
        find(
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;
        /**
        * @see _.find
        * @param _.where style callback
        */
        find<W>(
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.where style callback
        */
        find(
            pluckValue: string): T;
    }

    //_.findLast
    interface LoDashStatic {
        /**
        * This method is like _.find except that it iterates over elements of a collection from
        * right to left.
        * @param collection Searches for a value in this list.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return The found element, else undefined.
        **/
        findLast<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        findLast<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        **/
        findLast<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        findLast<W, T>(
            collection: Array<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        findLast<W, T>(
            collection: List<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.pluck style callback
        **/
        findLast<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        findLast<T>(
            collection: Array<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        findLast<T>(
            collection: List<T>,
            pluckValue: string): T;

        /**
        * @see _.find
        * @param _.where style callback
        **/
        findLast<T>(
            collection: Dictionary<T>,
            pluckValue: string): T;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.findLast
        */
        findLast(
            callback: ListIterator<T, boolean>,
            thisArg?: any): T;
        /**
        * @see _.findLast
        * @param _.where style callback
        */
        findLast<W>(
            whereValue: W): T;

        /**
        * @see _.findLast
        * @param _.where style callback
        */
        findLast(
            pluckValue: string): T;
    }

    //_.forEach
    interface LoDashStatic {
        /**
        * Iterates over elements of a collection, executing the callback for each element.
        * The callback is bound to thisArg and invoked with three arguments; (value, index|key,
        * collection). Callbacks may exit iteration early by explicitly returning false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        **/
        forEach<T>(
            collection: Array<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): Array<T>;

        /**
        * @see _.forEach
        **/
        forEach<T>(
            collection: List<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): List<T>;

        /**
        * @see _.forEach
        **/
        forEach<T extends {}>(
            object: Dictionary<T>,
            callback: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;

        /**
        * @see _.each
        **/
        forEach<T extends {}, TValue>(
            object: T,
            callback: ObjectIterator<TValue, void>,
            thisArg?: any): T

        /**
        * @see _.forEach
        **/
        each<T>(
            collection: Array<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): Array<T>;

        /**
        * @see _.forEach
        **/
        each<T>(
            collection: List<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): List<T>;

        /**
        * @see _.forEach
        * @param object The object to iterate over
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        **/
        each<T extends {}>(
            object: Dictionary<T>,
            callback: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;

        /**
        * @see _.each
        **/
        each<T extends {}, TValue>(
            object: T,
            callback: ObjectIterator<TValue, void>,
            thisArg?: any): T
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.forEach
        **/
        forEach(
            callback: ListIterator<T, void>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.forEach
        **/
        each(
            callback: ListIterator<T, void>,
            thisArg?: any): LoDashArrayWrapper<T>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.forEach
        **/
        forEach<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): LoDashObjectWrapper<T>;

        /**
        * @see _.forEach
        **/
        each<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): LoDashObjectWrapper<T>;
    }

    //_.forEachRight
    interface LoDashStatic {
        /**
        * This method is like _.forEach except that it iterates over elements of a
        * collection from right to left.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        **/
        forEachRight<T>(
            collection: Array<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): Array<T>;

        /**
        * @see _.forEachRight
        **/
        forEachRight<T>(
            collection: List<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): List<T>;

        /**
        * @see _.forEachRight
        **/
        forEachRight<T extends {}>(
            object: Dictionary<T>,
            callback: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;

        /**
        * @see _.forEachRight
        **/
        eachRight<T>(
            collection: Array<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): Array<T>;

        /**
        * @see _.forEachRight
        **/
        eachRight<T>(
            collection: List<T>,
            callback: ListIterator<T, void>,
            thisArg?: any): List<T>;

        /**
        * @see _.forEachRight
        * @param object The object to iterate over
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        **/
        eachRight<T extends {}>(
            object: Dictionary<T>,
            callback: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.forEachRight
        **/
        forEachRight(
            callback: ListIterator<T, void>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.forEachRight
        **/
        eachRight(
            callback: ListIterator<T, void>,
            thisArg?: any): LoDashArrayWrapper<T>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.forEachRight
        **/
        forEachRight<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): LoDashObjectWrapper<Dictionary<T>>;

        /**
        * @see _.forEachRight
        * @param object The object to iterate over
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        **/
        eachRight<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): LoDashObjectWrapper<Dictionary<T>>;
    }

    //_.groupBy
    interface LoDashStatic {
        /**
        * Creates an object composed of keys generated from the results of running each element
        * of a collection through the callback. The corresponding value of each key is an array
        * of the elements responsible for generating the key. The callback is bound to thisArg
        * and invoked with three arguments; (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return Returns the composed aggregate object.
        **/
        groupBy<T>(
            collection: Array<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): Dictionary<T[]>;

        /**
        * @see _.groupBy
        **/
        groupBy<T>(
            collection: List<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): Dictionary<T[]>;

        /**
        * @see _.groupBy
        * @param pluckValue _.pluck style callback
        **/
        groupBy<T>(
            collection: Array<T>,
            pluckValue: string): Dictionary<T[]>;

        /**
        * @see _.groupBy
        * @param pluckValue _.pluck style callback
        **/
        groupBy<T>(
            collection: List<T>,
            pluckValue: string): Dictionary<T[]>;

        /**
        * @see _.groupBy
        * @param whereValue _.where style callback
        **/
        groupBy<W, T>(
            collection: Array<T>,
            whereValue: W): Dictionary<T[]>;

        /**
        * @see _.groupBy
        * @param whereValue _.where style callback
        **/
        groupBy<W, T>(
            collection: List<T>,
            whereValue: W): Dictionary<T[]>;

        /**
        * @see _.groupBy
        **/
        groupBy<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): Dictionary<T[]>;

        /**
        * @see _.groupBy
        * @param pluckValue _.pluck style callback
        **/
        groupBy<TValue>(
            collection: Dictionary<TValue>,
            pluckValue: string): Dictionary<TValue[]>;

        /**
        * @see _.groupBy
        * @param whereValue _.where style callback
        **/
        groupBy<W, TValue>(
            collection: Dictionary<TValue>,
            whereValue: W): Dictionary<TValue[]>;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.groupBy
        **/
        groupBy(
            callback: ListIterator<T, any>,
            thisArg?: any): _.LoDashObjectWrapper<_.Dictionary<T[]>>;

        /**
        * @see _.groupBy
        **/
        groupBy(
            pluckValue: string): _.LoDashObjectWrapper<_.Dictionary<T[]>>;

        /**
        * @see _.groupBy
        **/
        groupBy<W>(
            whereValue: W): _.LoDashObjectWrapper<_.Dictionary<T[]>>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.groupBy
        **/
        groupBy<TValue>(
            callback: ListIterator<TValue, any>,
            thisArg?: any): _.LoDashObjectWrapper<_.Dictionary<TValue[]>>;

        /**
        * @see _.groupBy
        **/
        groupBy<TValue>(
            pluckValue: string): _.LoDashObjectWrapper<_.Dictionary<TValue[]>>;

        /**
        * @see _.groupBy
        **/
        groupBy<W, TValue>(
            whereValue: W): _.LoDashObjectWrapper<_.Dictionary<TValue[]>>;
    }

    //_.indexBy
    interface LoDashStatic {
        /**
        * Creates an object composed of keys generated from the results of running each element
        * of the collection through the given callback. The corresponding value of each key is
        * the last element responsible for generating the key. The callback is bound to thisArg
        * and invoked with three arguments; (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return Returns the composed aggregate object.
        **/
        indexBy<T>(
            list: Array<T>,
            iterator: ListIterator<T, any>,
            context?: any): Dictionary<T>;

        /**
        * @see _.indexBy
        **/
        indexBy<T>(
            list: List<T>,
            iterator: ListIterator<T, any>,
            context?: any): Dictionary<T>;

        /**
        * @see _.indexBy
        * @param pluckValue _.pluck style callback
        **/
        indexBy<T>(
            collection: Array<T>,
            pluckValue: string): Dictionary<T>;

        /**
        * @see _.indexBy
        * @param pluckValue _.pluck style callback
        **/
        indexBy<T>(
            collection: List<T>,
            pluckValue: string): Dictionary<T>;

        /**
        * @see _.indexBy
        * @param whereValue _.where style callback
        **/
        indexBy<W, T>(
            collection: Array<T>,
            whereValue: W): Dictionary<T>;

        /**
        * @see _.indexBy
        * @param whereValue _.where style callback
        **/
        indexBy<W, T>(
            collection: List<T>,
            whereValue: W): Dictionary<T>;
    }

    //_.invoke
    interface LoDashStatic {
        /**
        * Invokes the method named by methodName on each element in the collection returning
        * an array of the results of each invoked method. Additional arguments will be provided
        * to each invoked method. If methodName is a function it will be invoked for, and this
        * bound to, each element in the collection.
        * @param collection The collection to iterate over.
        * @param methodName The name of the method to invoke.
        * @param args Arguments to invoke the method with.
        **/
        invoke<T extends {}>(
            collection: Array<T>,
            methodName: string,
            ...args: any[]): any;

        /**
        * @see _.invoke
        **/
        invoke<T extends {}>(
            collection: List<T>,
            methodName: string,
            ...args: any[]): any;

        /**
        * @see _.invoke
        **/
        invoke<T extends {}>(
            collection: Dictionary<T>,
            methodName: string,
            ...args: any[]): any;

        /**
        * @see _.invoke
        **/
        invoke<T extends {}>(
            collection: Array<T>,
            method: Function,
            ...args: any[]): any;

        /**
        * @see _.invoke
        **/
        invoke<T extends {}>(
            collection: List<T>,
            method: Function,
            ...args: any[]): any;

        /**
        * @see _.invoke
        **/
        invoke<T extends {}>(
            collection: Dictionary<T>,
            method: Function,
            ...args: any[]): any;
    }

    //_.map
    interface LoDashStatic {
        /**
        * Creates an array of values by running each element in the collection through the callback.
        * The callback is bound to thisArg and invoked with three arguments; (value, index|key,
        * collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will return
        * the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return true
        * for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param theArg The this binding of callback.
        * @return The mapped array result.
        **/
        map<T, TResult>(
            collection: Array<T>,
            callback: ListIterator<T, TResult>,
            thisArg?: any): TResult[];

        /**
        * @see _.map
        **/
        map<T, TResult>(
            collection: List<T>,
            callback: ListIterator<T, TResult>,
            thisArg?: any): TResult[];

        /**
        * @see _.map
        * @param object The object to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg `this` object in `iterator`, optional.
        * @return The mapped object result.
        **/
        map<T extends {}, TResult>(
            object: Dictionary<T>,
            callback: ObjectIterator<T, TResult>,
            thisArg?: any): TResult[];

        /**
        * @see _.map
        * @param pluckValue _.pluck style callback
        **/
        map<T, TResult>(
            collection: Array<T>,
            pluckValue: string): TResult[];

        /**
        * @see _.map
        * @param pluckValue _.pluck style callback
        **/
        map<T, TResult>(
            collection: List<T>,
            pluckValue: string): TResult[];

        /**
        * @see _.map
        **/
        collect<T, TResult>(
            collection: Array<T>,
            callback: ListIterator<T, TResult>,
            thisArg?: any): TResult[];

        /**
        * @see _.map
        **/
        collect<T, TResult>(
            collection: List<T>,
            callback: ListIterator<T, TResult>,
            thisArg?: any): TResult[];

        /**
        * @see _.map
        **/
        collect<T extends {}, TResult>(
            object: Dictionary<T>,
            callback: ObjectIterator<T, TResult>,
            thisArg?: any): TResult[];

        /**
        * @see _.map
        **/
        collect<T, TResult>(
            collection: Array<T>,
            pluckValue: string): TResult[];

        /**
        * @see _.map
        **/
        collect<T, TResult>(
            collection: List<T>,
            pluckValue: string): TResult[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.map
        **/
        map<TResult>(
            callback: ListIterator<T, TResult>,
            thisArg?: any): LoDashArrayWrapper<TResult>;

        /**
        * @see _.map
        * @param pluckValue _.pluck style callback
        **/
        map<TResult>(
            pluckValue: string): LoDashArrayWrapper<TResult>;

        /**
        * @see _.map
        **/
        collect<TResult>(
            callback: ListIterator<T, TResult>,
            thisArg?: any): LoDashArrayWrapper<TResult>;

        /**
        * @see _.map
        **/
        collect<TResult>(
            pluckValue: string): LoDashArrayWrapper<TResult>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.map
        **/
        map<T extends {}, TResult>(
            callback: ObjectIterator<T, TResult>,
            thisArg?: any): LoDashArrayWrapper<TResult>;

        /**
        * @see _.map
        **/
        collect<T extends {}, TResult>(
            callback: ObjectIterator<T, TResult>,
            thisArg?: any): LoDashArrayWrapper<TResult>;
    }

    //_.max
    interface LoDashStatic {
        /**
        * Retrieves the maximum value of a collection. If the collection is empty or falsey -Infinity is
        * returned. If a callback is provided it will be executed for each value in the collection to
        * generate the criterion by which the value is ranked. The callback is bound to thisArg and invoked
        * with three arguments; (value, index, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will return the
        * property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return true for
        * elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return Returns the maximum value.
        **/
        max<T>(
            collection: Array<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): T;

        /**
        * @see _.max
        **/
        max<T>(
            collection: List<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): T;

        /**
        * @see _.max
        **/
        max<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): T;

        /**
        * @see _.max
        * @param pluckValue _.pluck style callback
        **/
        max<T>(
            collection: Array<T>,
            pluckValue: string): T;

        /**
        * @see _.max
        * @param pluckValue _.pluck style callback
        **/
        max<T>(
            collection: List<T>,
            pluckValue: string): T;

        /**
        * @see _.max
        * @param pluckValue _.pluck style callback
        **/
        max<T>(
            collection: Dictionary<T>,
            pluckValue: string): T;

        /**
        * @see _.max
        * @param whereValue _.where style callback
        **/
        max<W, T>(
            collection: Array<T>,
            whereValue: W): T;

        /**
        * @see _.max
        * @param whereValue _.where style callback
        **/
        max<W, T>(
            collection: List<T>,
            whereValue: W): T;

        /**
        * @see _.max
        * @param whereValue _.where style callback
        **/
        max<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.max
        **/
        max(
            callback?: ListIterator<T, any>,
            thisArg?: any): LoDashWrapper<T>;

        /**
        * @see _.max
        * @param pluckValue _.pluck style callback
        **/
        max(
            pluckValue: string): LoDashWrapper<T>;

        /**
        * @see _.max
        * @param whereValue _.where style callback
        **/
        max<W>(
            whereValue: W): LoDashWrapper<T>;
    }

    //_.min
    interface LoDashStatic {
        /**
        * Retrieves the minimum value of a collection. If the collection is empty or falsey
        * Infinity is returned. If a callback is provided it will be executed for each value
        * in the collection to generate the criterion by which the value is ranked. The callback
        * is bound to thisArg and invoked with three arguments; (value, index, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback
        * will return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will
        * return true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return Returns the maximum value.
        **/
        min<T>(
            collection: Array<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): T;

        /**
        * @see _.min
        **/
        min<T>(
            collection: List<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): T;

        /**
        * @see _.min
        **/
        min<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, any>,
            thisArg?: any): T;

        /**
        * @see _.min
        * @param pluckValue _.pluck style callback
        **/
        min<T>(
            collection: Array<T>,
            pluckValue: string): T;

        /**
        * @see _.min
        * @param pluckValue _.pluck style callback
        **/
        min<T>(
            collection: List<T>,
            pluckValue: string): T;

        /**
        * @see _.min
        * @param pluckValue _.pluck style callback
        **/
        min<T>(
            collection: Dictionary<T>,
            pluckValue: string): T;

        /**
        * @see _.min
        * @param whereValue _.where style callback
        **/
        min<W, T>(
            collection: Array<T>,
            whereValue: W): T;

        /**
        * @see _.min
        * @param whereValue _.where style callback
        **/
        min<W, T>(
            collection: List<T>,
            whereValue: W): T;

        /**
        * @see _.min
        * @param whereValue _.where style callback
        **/
        min<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T;
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.min
        **/
        min(
            callback?: ListIterator<T, any>,
            thisArg?: any): LoDashWrapper<T>;

        /**
        * @see _.min
        * @param pluckValue _.pluck style callback
        **/
        min(
            pluckValue: string): LoDashWrapper<T>;

        /**
        * @see _.min
        * @param whereValue _.where style callback
        **/
        min<W>(
            whereValue: W): LoDashWrapper<T>;
    }

    //_.pluck
    interface LoDashStatic {
        /**
        * Retrieves the value of a specified property from all elements in the collection.
        * @param collection The collection to iterate over.
        * @param property The property to pluck.
        * @return A new array of property values.
        **/
        pluck<T extends {}>(
            collection: Array<T>,
            property: string): any[];

        /**
        * @see _.pluck
        **/
        pluck<T extends {}>(
            collection: List<T>,
            property: string): any[];

        /**
        * @see _.pluck
        **/
        pluck<T extends {}>(
            collection: Dictionary<T>,
            property: string): any[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.pluck
        **/
        pluck<TResult>(
            property: string): LoDashArrayWrapper<TResult>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.pluck
        **/
        pluck<TResult>(
            property: string): LoDashArrayWrapper<TResult>;
    }

    //_.reduce
    interface LoDashStatic {
        /**
        * Reduces a collection to a value which is the accumulated result of running each
        * element in the collection through the callback, where each successive callback execution
        * consumes the return value of the previous execution. If accumulator is not provided the
        * first element of the collection will be used as the initial accumulator value. The callback
        * is bound to thisArg and invoked with four arguments; (accumulator, value, index|key, collection).
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param accumulator Initial value of the accumulator.
        * @param thisArg The this binding of callback.
        * @return Returns the accumulated value.
        **/
        reduce<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;
    }

    interface LoDashArrayWrapper<T> {
         /**
        * @see _.reduce
        **/
        reduce<TResult>(
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<TResult>(
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<TResult>(
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<TResult>(
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<TResult>(
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<TResult>(
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;
    }

    interface LoDashObjectWrapper<T> {
         /**
        * @see _.reduce
        **/
        reduce<TValue, TResult>(
            callback: MemoIterator<TValue, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        reduce<TValue, TResult>(
            callback: MemoIterator<TValue, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<TValue, TResult>(
            callback: MemoIterator<TValue, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        inject<TValue, TResult>(
            callback: MemoIterator<TValue, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<TValue, TResult>(
            callback: MemoIterator<TValue, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduce
        **/
        foldl<TValue, TResult>(
            callback: MemoIterator<TValue, TResult>,
            thisArg?: any): TResult;
    }

    //_.reduceRight
    interface LoDashStatic {
        /**
        * This method is like _.reduce except that it iterates over elements of a collection from
        * right to left.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param accumulator Initial value of the accumulator.
        * @param thisArg The this binding of callback.
        * @return The accumulated value.
        **/
        reduceRight<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        reduceRight<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        reduceRight<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        reduceRight<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        reduceRight<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        reduceRight<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        foldr<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        foldr<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        foldr<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            accumulator: TResult,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        foldr<T, TResult>(
            collection: Array<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        foldr<T, TResult>(
            collection: List<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;

        /**
        * @see _.reduceRight
        **/
        foldr<T, TResult>(
            collection: Dictionary<T>,
            callback: MemoIterator<T, TResult>,
            thisArg?: any): TResult;
    }

    //_.reject
    interface LoDashStatic {
        /**
        * The opposite of _.filter this method returns the elements of a collection that
        * the callback does not return truey for.
        *
        * If a property name is provided for callback the created "_.pluck" style callback
        * will return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will
        * return true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return A new array of elements that failed the callback check.
        **/
        reject<T>(
            collection: Array<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.reject
        **/
        reject<T>(
            collection: List<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.reject
        **/
        reject<T>(
            collection: Dictionary<T>,
            callback: ListIterator<T, boolean>,
            thisArg?: any): T[];

        /**
        * @see _.reject
        * @param pluckValue _.pluck style callback
        **/
        reject<T>(
            collection: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.reject
        * @param pluckValue _.pluck style callback
        **/
        reject<T>(
            collection: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.reject
        * @param pluckValue _.pluck style callback
        **/
        reject<T>(
            collection: Dictionary<T>,
            pluckValue: string): T[];

        /**
        * @see _.reject
        * @param whereValue _.where style callback
        **/
        reject<W, T>(
            collection: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.reject
        * @param whereValue _.where style callback
        **/
        reject<W, T>(
            collection: List<T>,
            whereValue: W): T[];

        /**
        * @see _.reject
        * @param whereValue _.where style callback
        **/
        reject<W, T>(
            collection: Dictionary<T>,
            whereValue: W): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.reject
        **/
        reject(
            callback: ListIterator<T, boolean>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.reject
        * @param pluckValue _.pluck style callback
        **/
        reject(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.reject
        * @param whereValue _.where style callback
        **/
        reject<W>(whereValue: W): LoDashArrayWrapper<T>;
    }

    //_.sample
    interface LoDashStatic {
        /**
        * Retrieves a random element or n random elements from a collection.
        * @param collection The collection to sample.
        * @return Returns the random sample(s) of collection.
        **/
        sample<T>(collection: Array<T>): T;

        /**
        * @see _.sample
        **/
        sample<T>(collection: List<T>): T;

        /**
        * @see _.sample
        **/
        sample<T>(collection: Dictionary<T>): T;

        /**
        * @see _.sample
        * @param n The number of elements to sample.
        **/
        sample<T>(collection: Array<T>, n: number): T[];

        /**
        * @see _.sample
        * @param n The number of elements to sample.
        **/
        sample<T>(collection: List<T>, n: number): T[];

        /**
        * @see _.sample
        * @param n The number of elements to sample.
        **/
        sample<T>(collection: Dictionary<T>, n: number): T[];
    }

    //_.shuffle
    interface LoDashStatic {
        /**
        * Creates an array of shuffled values, using a version of the Fisher-Yates shuffle.
        * See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
        * @param collection The collection to shuffle.
        * @return Returns a new shuffled collection.
        **/
        shuffle<T>(collection: Array<T>): T[];

        /**
        * @see _.shuffle
        **/
        shuffle<T>(collection: List<T>): T[];

        /**
        * @see _.shuffle
        **/
        shuffle<T>(collection: Dictionary<T>): T[];
    }

    //_.size
    interface LoDashStatic {
        /**
        * Gets the size of the collection by returning collection.length for arrays and array-like
        * objects or the number of own enumerable properties for objects.
        * @param collection The collection to inspect.
        * @return collection.length
        **/
        size<T>(collection: Array<T>): number;

        /**
        * @see _.size
        **/
        size<T>(collection: List<T>): number;

        /**
        * @see _.size
        * @param object The object to inspect
        * @return The number of own enumerable properties.
        **/
        size<T extends {}>(object: T): number;

        /**
        * @see _.size
        * @param aString The string to inspect
        * @return The length of aString
        **/
        size(aString: string): number;
    }

    //_.some
    interface LoDashStatic {
        /**
        * Checks if the callback returns a truey value for any element of a collection. The function
        * returns as soon as it finds a passing value and does not iterate over the entire collection.
        * The callback is bound to thisArg and invoked with three arguments; (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will return
        * the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return true for
        * elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return True if any element passed the callback check, else false.
        **/
        some<T>(
            collection: Array<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.some
        **/
        some<T>(
            collection: List<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.some
        **/
        some<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
         * @see _.some
         **/
        some(
            collection: {},
            callback?: ListIterator<{}, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.some
        * @param pluckValue _.pluck style callback
        **/
        some<T>(
            collection: Array<T>,
            pluckValue: string): boolean;

        /**
        * @see _.some
        * @param pluckValue _.pluck style callback
        **/
        some<T>(
            collection: List<T>,
            pluckValue: string): boolean;

        /**
        * @see _.some
        * @param pluckValue _.pluck style callback
        **/
        some<T>(
            collection: Dictionary<T>,
            pluckValue: string): boolean;

        /**
        * @see _.some
        * @param whereValue _.where style callback
        **/
        some<W, T>(
            collection: Array<T>,
            whereValue: W): boolean;

        /**
        * @see _.some
        * @param whereValue _.where style callback
        **/
        some<W, T>(
            collection: List<T>,
            whereValue: W): boolean;

        /**
        * @see _.some
        * @param whereValue _.where style callback
        **/
        some<W, T>(
            collection: Dictionary<T>,
            whereValue: W): boolean;

        /**
        * @see _.some
        **/
        any<T>(
            collection: Array<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.some
        **/
        any<T>(
            collection: List<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.some
        **/
        any<T>(
            collection: Dictionary<T>,
            callback?: ListIterator<T, boolean>,
            thisArg?: any): boolean;

        /**
         * @see _.some
         **/
        any(
            collection: {},
            callback?: ListIterator<{}, boolean>,
            thisArg?: any): boolean;

        /**
        * @see _.some
        * @param pluckValue _.pluck style callback
        **/
        any<T>(
            collection: Array<T>,
            pluckValue: string): boolean;

        /**
        * @see _.some
        * @param pluckValue _.pluck style callback
        **/
        any<T>(
            collection: List<T>,
            pluckValue: string): boolean;

        /**
        * @see _.some
        * @param pluckValue _.pluck style callback
        **/
        any<T>(
            collection: Dictionary<T>,
            pluckValue: string): boolean;

        /**
        * @see _.some
        * @param whereValue _.where style callback
        **/
        any<W, T>(
            collection: Array<T>,
            whereValue: W): boolean;

        /**
        * @see _.some
        * @param whereValue _.where style callback
        **/
        any<W, T>(
            collection: List<T>,
            whereValue: W): boolean;

        /**
        * @see _.some
        * @param whereValue _.where style callback
        **/
        any<W, T>(
            collection: Dictionary<T>,
            whereValue: W): boolean;
    }

    //_.sortBy
    interface LoDashStatic {
        /**
        * Creates an array of elements, sorted in ascending order by the results of running each
        * element in a collection through the callback. This method performs a stable sort, that
        * is, it will preserve the original sort order of equal elements. The callback is bound
        * to thisArg and invoked with three arguments; (value, index|key, collection).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will
        * return the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return
        * true for elements that have the properties of the given object, else false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return A new array of sorted elements.
        **/
        sortBy<T, TSort>(
            collection: Array<T>,
            callback?: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.sortBy
        **/
        sortBy<T, TSort>(
            collection: List<T>,
            callback?: ListIterator<T, TSort>,
            thisArg?: any): T[];

        /**
        * @see _.sortBy
        * @param pluckValue _.pluck style callback
        **/
        sortBy<T>(
            collection: Array<T>,
            pluckValue: string): T[];

        /**
        * @see _.sortBy
        * @param pluckValue _.pluck style callback
        **/
        sortBy<T>(
            collection: List<T>,
            pluckValue: string): T[];

        /**
        * @see _.sortBy
        * @param whereValue _.where style callback
        **/
        sortBy<W, T>(
            collection: Array<T>,
            whereValue: W): T[];

        /**
        * @see _.sortBy
        * @param whereValue _.where style callback
        **/
        sortBy<W, T>(
            collection: List<T>,
            whereValue: W): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.sortBy
        **/
        sortBy<TSort>(
            callback?: ListIterator<T, TSort>,
            thisArg?: any): LoDashArrayWrapper<T>;

        /**
        * @see _.sortBy
        * @param pluckValue _.pluck style callback
        **/
        sortBy(pluckValue: string): LoDashArrayWrapper<T>;

        /**
        * @see _.sortBy
        * @param whereValue _.where style callback
        **/
        sortBy<W>(whereValue: W): LoDashArrayWrapper<T>;
    }

    //_.toArray
    interface LoDashStatic {
        /**
        * Converts the collection to an array.
        * @param collection The collection to convert.
        * @return The new converted array.
        **/
        toArray<T>(collection: Array<T>): T[];

        /**
        * @see _.toArray
        **/
        toArray<T>(collection: List<T>): T[];

        /**
        * @see _.toArray
        **/
        toArray<T>(collection: Dictionary<T>): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.toArray
        **/
        toArray(): LoDashArrayWrapper<T>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.toArray
        **/
        toArray<TValue>(): LoDashArrayWrapper<TValue>;
    }

    //_.where
    interface LoDashStatic {
        /**
        * Performs a deep comparison of each element in a collection to the given properties
        * object, returning an array of all elements that have equivalent property values.
        * @param collection The collection to iterate over.
        * @param properties The object of property values to filter by.
        * @return A new array of elements that have the given properties.
        **/
        where<T, U extends {}>(
            list: Array<T>,
            properties: U): T[];

        /**
        * @see _.where
        **/
        where<T, U extends {}>(
            list: List<T>,
            properties: U): T[];

        /**
        * @see _.where
        **/
        where<T, U extends {}>(
            list: Dictionary<T>,
            properties: U): T[];
    }

    interface LoDashArrayWrapper<T> {
        /**
        * @see _.where
        **/
        where<T, U extends {}>(properties: U): LoDashArrayWrapper<T>;
    }

    /*************
     * Functions *
     *************/

    //_.after
    interface LoDashStatic {
        /**
        * Creates a function that executes func, with the this binding and arguments of the
        * created function, only after being called n times.
        * @param n The number of times the function must be called before func is executed.
        * @param func The function to restrict.
        * @return The new restricted function.
        **/
        after(
            n: number,
            func: Function): Function;
    }

    interface LoDashWrapper<T> {
        /**
        * @see _.after
        **/
        after(func: Function): LoDashObjectWrapper<Function>;
    }

    //_.bind
    interface LoDashStatic {
        /**
        * Creates a function that, when called, invokes func with the this binding of thisArg
        * and prepends any additional bind arguments to those provided to the bound function.
        * @param func The function to bind.
        * @param thisArg The this binding of func.
        * @param args Arguments to be partially applied.
        * @return The new bound function.
        **/
        bind(
            func: Function,
            thisArg: any,
            ...args: any[]): () => any;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.bind
        **/
        bind(
            thisArg: any,
            ...args: any[]): LoDashObjectWrapper<() => any>;
    }

    //_.bindAll
    interface LoDashStatic {
        /**
        * Binds methods of an object to the object itself, overwriting the existing method. Method
        * names may be specified as individual arguments or as arrays of method names. If no method
        * names are provided all the function properties of object will be bound.
        * @param object The object to bind and assign the bound methods to.
        * @param methodNames The object method names to bind, specified as individual method names
        * or arrays of method names.
        * @return object
        **/
        bindAll<T>(
            object: T,
            ...methodNames: string[]): T;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.bindAll
        **/
        bindAll(...methodNames: string[]): LoDashWrapper<T>;
    }

    //_.bindKey
    interface LoDashStatic {
        /**
        * Creates a function that, when called, invokes the method at object[key] and prepends any
        * additional bindKey arguments to those provided to the bound function. This method differs
        * from _.bind by allowing bound functions to reference methods that will be redefined or don't
        * yet exist. See http://michaux.ca/articles/lazy-function-definition-pattern.
        * @param object The object the method belongs to.
        * @param key The key of the method.
        * @param args Arguments to be partially applied.
        * @return The new bound function.
        **/
        bindKey<T>(
            object: T,
            key: string,
            ...args: any[]): Function;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.bindKey
        **/
        bindKey(
            key: string,
            ...args: any[]): LoDashObjectWrapper<Function>;
    }

    //_.compose
    interface LoDashStatic {
        /**
        * Creates a function that is the composition of the provided functions, where each function
        * consumes the return value of the function that follows. For example, composing the functions
        * f(), g(), and h() produces f(g(h())). Each function is executed with the this binding of the
        * composed function.
        * @param funcs Functions to compose.
        * @return The new composed function.
        **/
        compose(...funcs: Function[]): Function;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.compose
        **/
        compose(...funcs: Function[]): LoDashObjectWrapper<Function>;
    }

    //_.createCallback
    interface LoDashStatic {
        /**
        * Produces a callback bound to an optional thisArg. If func is a property name the created
        * callback will return the property value for a given element. If func is an object the created
        * callback will return true for elements that contain the equivalent object properties,
        * otherwise it will return false.
        * @param func The value to convert to a callback.
        * @param thisArg The this binding of the created callback.
        * @param argCount The number of arguments the callback accepts.
        * @return A callback function.
        **/
        createCallback(
            func: string,
            thisArg?: any,
            argCount?: number): () => any;

        /**
        * @see _.createCallback
        **/
        createCallback(
            func: Dictionary<any>,
            thisArg?: any,
            argCount?: number): () => boolean;
    }

    interface LoDashWrapper<T> {
        /**
        * @see _.createCallback
        **/
        createCallback(
            thisArg?: any,
            argCount?: number): LoDashObjectWrapper<() => any>;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.createCallback
        **/
        createCallback(
            thisArg?: any,
            argCount?: number): LoDashObjectWrapper<() => any>;
    }

    //_.curry
    interface LoDashStatic {
        /**
        * Creates a function which accepts one or more arguments of func that when invoked either
        * executes func returning its result, if all func arguments have been provided, or returns
        * a function that accepts one or more of the remaining func arguments, and so on. The arity
        * of func can be specified if func.length is not sufficient.
        * @param func The function to curry.
        * @param arity The arity of func.
        * @return The new curried function.
        **/
        curry(
            func: Function,
            arity?: number): Function;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.curry
        **/
        curry(arity?: number): LoDashObjectWrapper<Function>;
    }

    //_.debounce
    interface LoDashStatic {
        /**
        * Creates a function that will delay the execution of func until after wait milliseconds have
        * elapsed since the last time it was invoked. Provide an options object to indicate that func
        * should be invoked on the leading and/or trailing edge of the wait timeout. Subsequent calls
        * to the debounced function will return the result of the last func call.
        *
        * Note: If leading and trailing options are true func will be called on the trailing edge of
        * the timeout only if the the debounced function is invoked more than once during the wait
        * timeout.
        * @param func The function to debounce.
        * @param wait The number of milliseconds to delay.
        * @param options The options object.
        * @param options.leading Specify execution on the leading edge of the timeout.
        * @param options.maxWait The maximum time func is allowed to be delayed before it’s called.
        * @param options.trailing Specify execution on the trailing edge of the timeout.
        * @return The new debounced function.
        **/
        debounce<T extends Function>(
            func: T,
            wait: number,
            options?: DebounceSettings): T;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.debounce
        **/
        debounce(
            wait: number,
            options?: DebounceSettings): LoDashObjectWrapper<Function>;
    }

    interface DebounceSettings {
        /**
        * Specify execution on the leading edge of the timeout.
        **/
        leading?: boolean;

        /**
        * The maximum time func is allowed to be delayed before it’s called.
        **/
        maxWait?: number;

        /**
        * Specify execution on the trailing edge of the timeout.
        **/
        trailing?: boolean;
    }

    //_.defer
    interface LoDashStatic {
        /**
        * Defers executing the func function until the current call stack has cleared. Additional
        * arguments will be provided to func when it is invoked.
        * @param func The function to defer.
        * @param args Arguments to invoke the function with.
        * @return The timer id.
        **/
        defer(
            func: Function,
            ...args: any[]): number;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.defer
        **/
        defer(...args: any[]): LoDashWrapper<number>;
    }

    //_.delay
    interface LoDashStatic {
        /**
        * Executes the func function after wait milliseconds. Additional arguments will be provided
        * to func when it is invoked.
        * @param func The function to delay.
        * @param wait The number of milliseconds to delay execution.
        * @param args Arguments to invoke the function with.
        * @return The timer id.
        **/
        delay(
            func: Function,
            wait: number,
            ...args: any[]): number;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.delay
        **/
        delay(
            wait: number,
            ...args: any[]): LoDashWrapper<number>;
    }

    //_.memoize
    interface LoDashStatic {
        /**
        * Creates a function that memoizes the result of func. If resolver is provided it will be
        * used to determine the cache key for storing the result based on the arguments provided to
        * the memoized function. By default, the first argument provided to the memoized function is
        * used as the cache key. The func is executed with the this binding of the memoized function.
        * The result cache is exposed as the cache property on the memoized function.
        * @param func Computationally expensive function that will now memoized results.
        * @param resolver Hash function for storing the result of `fn`.
        * @return Returns the new memoizing function.
        **/
        memoize<T extends Function>(
            func: T,
            resolver?: Function): T;
    }

    //_.once
    interface LoDashStatic {
        /**
        * Creates a function that is restricted to execute func once. Repeat calls to the function
        * will return the value of the first call. The func is executed with the this binding of the
        * created function.
        * @param func Function to only execute once.
        * @return The new restricted function.
        **/
        once<T extends Function>(func: T): T;
    }

    //_.partial
    interface LoDashStatic {
        /**
        * Creates a function that, when called, invokes func with any additional partial arguments
        * prepended to those provided to the new function. This method is similar to _.bind except
        * it does not alter the this binding.
        * @param func The function to partially apply arguments to.
        * @param args Arguments to be partially applied.
        * @return The new partially applied function.
        **/
        partial(
            func: Function,
            ...args: any[]): Function;
    }

    //_.partialRight
    interface LoDashStatic {
        /**
        * This method is like _.partial except that partial arguments are appended to those provided
        * to the new function.
        * @param func The function to partially apply arguments to.
        * @param args Arguments to be partially applied.
        * @return The new partially applied function.
        **/
        partialRight(
            func: Function,
            ...args: any[]): Function;
    }

    //_.throttle
    interface LoDashStatic {
        /**
        * Creates a function that, when executed, will only call the func function at most once per
        * every wait milliseconds. Provide an options object to indicate that func should be invoked
        * on the leading and/or trailing edge of the wait timeout. Subsequent calls to the throttled
        * function will return the result of the last func call.
        *
        * Note: If leading and trailing options are true func will be called on the trailing edge of
        * the timeout only if the the throttled function is invoked more than once during the wait timeout.
        * @param func The function to throttle.
        * @param wait The number of milliseconds to throttle executions to.
        * @param options The options object.
        * @param options.leading Specify execution on the leading edge of the timeout.
        * @param options.trailing Specify execution on the trailing edge of the timeout.
        * @return The new throttled function.
        **/
        throttle<T extends Function>(
            func: T,
            wait: number,
            options?: ThrottleSettings): T;
    }

    interface ThrottleSettings {

        /**
        * If you'd like to disable the leading-edge call, pass this as false.
        **/
        leading?: boolean;

        /**
        * If you'd like to disable the execution on the trailing-edge, pass false.
        **/
        trailing?: boolean;
    }

    //_.wrap
    interface LoDashStatic {
        /**
        * Creates a function that provides value to the wrapper function as its first argument.
        * Additional arguments provided to the function are appended to those provided to the
        * wrapper function. The wrapper is executed with the this binding of the created function.
        * @param value The value to wrap.
        * @param wrapper The wrapper function.
        * @return The new function.
        **/
        wrap(
            value: any,
            wrapper: (func: Function, ...args: any[]) => any): Function;
    }

    /*************
     * Objects   *
     *************/

    //_.assign
    interface LoDashStatic {
        /**
        * Assigns own enumerable properties of source object(s) to the destination object. Subsequent
        * sources will overwrite property assignments of previous sources. If a callback is provided
        * it will be executed to produce the assigned values. The callback is bound to thisArg and
        * invoked with two arguments; (objectValue, sourceValue).
        * @param object The destination object.
        * @param s1-8 The source object(s)
        * @param callback The function to customize merging properties.
        * @param thisArg The this binding of callback.
        * @return The destination object.
        **/
        assign<P, T, S1, Value, Result>(
            object: T,
            s1: S1,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        assign<P, T, S1, S2, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        assign<P, T, S1, S2, S3, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            s3: S3,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        assign<P, T, S1, S2, S3, S4, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        extend<P, T, S1, Value, Result>(
            object: T,
            s1: S1,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        extend<P, T, S1, S2, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        extend<P, T, S1, S2, S3, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            s3: S3,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.assign
        **/
        extend<P, T, S1, S2, S3, S4, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.assign
        **/
        assign<S1, Value, TResult>(
            s1: S1,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;

        /**
        * @see _.assign
        **/
        assign<S1, S2, Value, TResult>(
            s1: S1,
            s2: S2,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;
        /**
        * @see _.assign
        **/
        assign<S1, S2, S3, Value, TResult>(
            s1: S1,
            s2: S2,
            s3: S3,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;
        /**
        * @see _.assign
        **/
        assign<S1, S2, S3, S4, Value, TResult>(
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;
        /**
        * @see _.assign
        **/
        assign<S1, S2, S3, S4, S5, Value, TResult>(
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            s5: S5,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;

        /**
        * @see _.assign
        **/
        extend<S1, Value, TResult>(
            s1: S1,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;

        /**
        * @see _.assign
        **/
        extend<S1, S2, Value, TResult>(
            s1: S1,
            s2: S2,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;
        /**
        * @see _.assign
        **/
        extend<S1, S2, S3, Value, TResult>(
            s1: S1,
            s2: S2,
            s3: S3,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;
        /**
        * @see _.assign
        **/
        extend<S1, S2, S3, S4, Value, TResult>(
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;
        /**
        * @see _.assign
        **/
        extend<S1, S2, S3, S4, S5, Value, TResult>(
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            s5: S5,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): TResult;

    }

    //_.clone
    interface LoDashStatic {
        /**
        * Creates a clone of value. If deep is true nested objects will also be cloned, otherwise
        * they will be assigned by reference. If a callback is provided it will be executed to produce
        * the cloned values. If the callback returns undefined cloning will be handled by the method
        * instead. The callback is bound to thisArg and invoked with one argument; (value).
        * @param value The value to clone.
        * @param deep Specify a deep clone.
        * @param callback The function to customize cloning values.
        * @param thisArg The this binding of callback.
        * @return The cloned value.
        **/
        clone<T>(
            value: T,
            deep?: boolean,
            callback?: (value: any) => any,
            thisArg?: any): T;
    }

    //_.cloneDeep
    interface LoDashStatic {
        /**
        * Creates a deep clone of value. If a callback is provided it will be executed to produce the
        * cloned values. If the callback returns undefined cloning will be handled by the method instead.
        * The callback is bound to thisArg and invoked with one argument; (value).
        *
        * Note: This method is loosely based on the structured clone algorithm. Functions and DOM nodes
        * are not cloned. The enumerable properties of arguments objects and objects created by constructors
        * other than Object are cloned to plain Object objects.
        * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
        * @param value The value to clone.
        * @param callback The function to customize cloning values.
        * @param thisArg The this binding of callback.
        * @return The cloned value.
        **/
        cloneDeep<T>(
            value: T,
            callback?: (value: any) => any,
            thisArg?: any): T;
    }

    //_.defaults
    interface LoDashStatic {
        /**
        * Assigns own enumerable properties of source object(s) to the destination object for all
        * destination properties that resolve to undefined. Once a property is set, additional defaults
        * of the same property will be ignored.
        * @param object The destination object.
        * @param sources The source objects.
        * @return The destination object.
        **/
        defaults<T, TResult>(
            object: T,
            ...sources: any[]): TResult;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.defaults
        **/
        defaults<T, TResult>(...sources: any[]): LoDashObjectWrapper<TResult>
    }

    //_.findKey
    interface LoDashStatic {
        /**
        * This method is like _.findIndex except that it returns the key of the first element that
        * passes the callback check, instead of the element itself.
        * @param object The object to search.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return The key of the found element, else undefined.
        **/
        findKey(
            object: any,
            callback: (value: any) => boolean,
            thisArg?: any): string;

        /**
        * @see _.findKey
        * @param pluckValue _.pluck style callback
        **/
        findKey(
            object: any,
            pluckValue: string): string;

        /**
        * @see _.findKey
        * @param whereValue _.where style callback
        **/
        findKey<W extends Dictionary<any>, T>(
            object: T,
            whereValue: W): string;
    }

    //_.findLastKey
    interface LoDashStatic {
        /**
        * This method is like _.findKey except that it iterates over elements of a collection in the opposite order.
        * @param object The object to search.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return The key of the found element, else undefined.
        **/
        findLastKey(
            object: any,
            callback: (value: any) => boolean,
            thisArg?: any): string;

        /**
        * @see _.findLastKey
        * @param pluckValue _.pluck style callback
        **/
        findLastKey(
            object: any,
            pluckValue: string): string;

        /**
        * @see _.findLastKey
        * @param whereValue _.where style callback
        **/
        findLastKey<W extends Dictionary<any>, T>(
            object: T,
            whereValue: W): string;
    }

    //_.forIn
    interface LoDashStatic {
        /**
        * Iterates over own and inherited enumerable properties of an object, executing the callback for
        * each property. The callback is bound to thisArg and invoked with three arguments; (value, key,
        * object). Callbacks may exit iteration early by explicitly returning false.
        * @param object The object to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return object
        **/
        forIn<T>(
            object: Dictionary<T>,
            callback?: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;

        /**
        * @see _.forIn
        **/
        forIn<T>(
            object: T,
            callback?: ObjectIterator<any, void>,
            thisArg?: any): T;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.forIn
        **/
        forIn<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): _.LoDashObjectWrapper<T>;
    }

    //_.forInRight
    interface LoDashStatic {
        /**
        * This method is like _.forIn except that it iterates over elements of a collection in the
        * opposite order.
        * @param object The object to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return object
        **/
        forInRight<T extends {}>(
            object: Dictionary<T>,
            callback?: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;

        /**
        * @see _.forInRight
        **/
        forInRight<T extends {}>(
            object: T,
            callback?: ObjectIterator<T, void>,
            thisArg?: any): T;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.forInRight
        **/
        forInRight<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): _.LoDashObjectWrapper<T>;
    }

    //_.forOwn
    interface LoDashStatic {
        /**
        * Iterates over own enumerable properties of an object, executing the callback for each
        * property. The callback is bound to thisArg and invoked with three arguments; (value, key,
        * object). Callbacks may exit iteration early by explicitly returning false.
        * @param object The object to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return object
        **/
        forOwn<T extends {}>(
            object: Dictionary<T>,
            callback?: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;

        /**
        * @see _.forOwn
        **/
        forOwn<T extends {}>(
            object: T,
            callback?: ObjectIterator<any, void>,
            thisArg?: any): T;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.forOwn
        **/
        forOwn<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): _.LoDashObjectWrapper<T>;
    }

    //_.forOwnRight
    interface LoDashStatic {
        /**
        * This method is like _.forOwn except that it iterates over elements of a collection in the
        * opposite order.
        * @param object The object to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        * @return object
        **/
        forOwnRight<T extends {}>(
            object: Dictionary<T>,
            callback?: ObjectIterator<T, void>,
            thisArg?: any): Dictionary<T>;
        /**
        * @see _.forOwnRight
        **/
        forOwnRight<T extends {}>(
            object: T,
            callback?: ObjectIterator<any, void>,
            thisArg?: any): T;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.forOwnRight
        **/
        forOwnRight<T extends {}>(
            callback: ObjectIterator<T, void>,
            thisArg?: any): _.LoDashObjectWrapper<T>;
    }

    //_.functions
    interface LoDashStatic {
        /**
        * Creates a sorted array of property names of all enumerable properties, own and inherited, of
        * object that have function values.
        * @param object The object to inspect.
        * @return An array of property names that have function values.
        **/
        functions(object: any): string[];

        /**
        * @see _functions
        **/
        methods(object: any): string[];
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.functions
        **/
        functions(): _.LoDashArrayWrapper<string>;

        /**
        * @see _.functions
        **/
        methods(): _.LoDashArrayWrapper<string>;
    }

    //_.has
    interface LoDashStatic {
        /**
        * Checks if the specified object property exists and is a direct property, instead of an
        * inherited property.
        * @param object The object to check.
        * @param property The property to check for.
        * @return True if key is a direct property, else false.
        **/
        has(object: any, property: string): boolean;
    }

    //_.invert
    interface LoDashStatic {
        /**
        * Creates an object composed of the inverted keys and values of the given object.
        * @param object The object to invert.
        * @return The created inverted object.
        **/
        invert(object: any): any;
    }

    //_.isArguments
    interface LoDashStatic {
        /**
        * Checks if value is an arguments object.
        * @param value The value to check.
        * @return True if the value is an arguments object, else false.
        **/
        isArguments(value: any): boolean;
    }

    //_.isArray
    interface LoDashStatic {
        /**
        * Checks if value is an array.
        * @param value The value to check.
        * @return True if the value is an array, else false.
        **/
        isArray(value: any): boolean;
    }

    //_.isBoolean
    interface LoDashStatic {
        /**
        * Checks if value is a boolean value.
        * @param value The value to check.
        * @return True if the value is a boolean value, else false.
        **/
        isBoolean(value: any): boolean;
    }

    //_.isDate
    interface LoDashStatic {
        /**
        * Checks if value is a date.
        * @param value The value to check.
        * @return True if the value is a date, else false.
        **/
        isDate(value: any): boolean;
    }

    //_.isElement
    interface LoDashStatic {
        /**
        * Checks if value is a DOM element.
        * @param value The value to check.
        * @return True if the value is a DOM element, else false.
        **/
        isElement(value: any): boolean;
    }

    //_.isEmpty
    interface LoDashStatic {
        /**
        * Checks if value is empty. Arrays, strings, or arguments objects with a length of 0 and objects
        * with no own enumerable properties are considered "empty".
        * @param value The value to inspect.
        * @return True if the value is empty, else false.
        **/
        isEmpty(value: any[]): boolean;

        /**
        * @see _.isEmpty
        **/
        isEmpty(value: Dictionary<any>): boolean;

        /**
        * @see _.isEmpty
        **/
        isEmpty(value: string): boolean;

        /**
        * @see _.isEmpty
        **/
        isEmpty(value: any): boolean;
    }

    //_.isEqual
    interface LoDashStatic {
        /**
        * Performs a deep comparison between two values to determine if they are equivalent to each
        * other. If a callback is provided it will be executed to compare values. If the callback
        * returns undefined comparisons will be handled by the method instead. The callback is bound to
        * thisArg and invoked with two arguments; (a, b).
        * @param a The value to compare.
        * @param b The other value to compare.
        * @param callback The function to customize comparing values.
        * @param thisArg The this binding of callback.
        * @return True if the values are equivalent, else false.
        **/
        isEqual(
            a: any,
            b: any,
            callback?: (a: any, b: any) => boolean,
            thisArg?: any): boolean;
    }

    //_.isFinite
    interface LoDashStatic {
        /**
        * Checks if value is, or can be coerced to, a finite number.
        *
        * Note: This is not the same as native isFinite which will return true for booleans and empty
        * strings. See http://es5.github.io/#x15.1.2.5.
        * @param value The value to check.
        * @return True if the value is finite, else false.
        **/
        isFinite(value: any): boolean;
    }

    //_.isFunction
    interface LoDashStatic {
        /**
        * Checks if value is a function.
        * @param value The value to check.
        * @return True if the value is a function, else false.
        **/
        isFunction(value: any): boolean;
    }

    //_.isNaN
    interface LoDashStatic {
        /**
        * Checks if value is NaN.
        *
        * Note: This is not the same as native isNaN which will return true for undefined and other
        * non-numeric values. See http://es5.github.io/#x15.1.2.4.
        * @param value The value to check.
        * @return True if the value is NaN, else false.
        **/
        isNaN(value: any): boolean;
    }

    //_.isNull
    interface LoDashStatic {
        /**
        * Checks if value is null.
        * @param value The value to check.
        * @return True if the value is null, else false.
        **/
        isNull(value: any): boolean;
    }

    //_.isNumber
    interface LoDashStatic {
        /**
        * Checks if value is a number.
        *
        * Note: NaN is considered a number. See http://es5.github.io/#x8.5.
        * @param value The value to check.
        * @return True if the value is a number, else false.
        **/
        isNumber(value: any): boolean;
    }

    //_.isObject
    interface LoDashStatic {
        /**
        * Checks if value is the language type of Object. (e.g. arrays, functions, objects, regexes,
        * new Number(0), and new String(''))
        * @param value The value to check.
        * @return True if the value is an object, else false.
        **/
        isObject(value: any): boolean;
    }

    //_.isPlainObject
    interface LoDashStatic {
        /**
        * Checks if value is an object created by the Object constructor.
        * @param value The value to check.
        * @return True if value is a plain object, else false.
        **/
        isPlainObject(value: any): boolean;
    }

    //_.isRegExp
    interface LoDashStatic {
        /**
        * Checks if value is a regular expression.
        * @param value The value to check.
        * @return True if the value is a regular expression, else false.
        **/
        isRegExp(value: any): boolean;
    }

    //_.isString
    interface LoDashStatic {
        /**
        * Checks if value is a string.
        * @param value The value to check.
        * @return True if the value is a string, else false.
        **/
        isString(value: any): boolean;
    }

    //_.isUndefined
    interface LoDashStatic {
        /**
        * Checks if value is undefined.
        * @param value The value to check.
        * @return True if the value is undefined, else false.
        **/
        isUndefined(value: any): boolean;
    }

    //_.keys
    interface LoDashStatic {
        /**
        * Creates an array composed of the own enumerable property names of an object.
        * @param object The object to inspect.
        * @return An array of property names.
        **/
        keys(object: any): string[];
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.keys
        **/
        keys(): LoDashArrayWrapper<string>
    }

    //_.mapValues
    interface LoDashStatic {
        /**
        * Creates an object with the same keys as object and values generated by running each own
        * enumerable property of object through the callback. The callback is bound to thisArg and
        * invoked with three arguments; (value, key, object).
        *
        * If a property name is provided for callback the created "_.pluck" style callback will return
        * the property value of the given element.
        *
        * If an object is provided for callback the created "_.where" style callback will return true
        * for elements that have the properties of the given object, else false.
        *
        * @param object The object to iterate over.
        * @param callback The function called per iteration.
        * @param thisArg `this` object in `iterator`, optional.
        * @return Returns a new object with values of the results of each callback execution.
        */
        mapValues<T, TResult>(obj: Dictionary<T>, callback: ObjectIterator<T, TResult>, thisArg?: any): Dictionary<TResult>;
        mapValues<T>(obj: Dictionary<T>, where: Dictionary<T>): Dictionary<boolean>;
        mapValues<T, TMapped>(obj: T, pluck: string): TMapped;
        mapValues<T>(obj: T, callback: ObjectIterator<any, any>, thisArg?: any): T;
    }

    //_.merge
    interface LoDashStatic {
        /**
        * Recursively merges own enumerable properties of the source object(s), that don't resolve
        * to undefined into the destination object. Subsequent sources will overwrite property
        * assignments of previous sources. If a callback is provided it will be executed to produce
        * the merged values of the destination and source properties. If the callback returns undefined
        * merging will be handled by the method instead. The callback is bound to thisArg and invoked
        * with two arguments; (objectValue, sourceValue).
        * @param object The destination object.
        * @param s1-8 The source object(s)
        * @param callback The function to customize merging properties.
        * @param thisArg The this binding of callback.
        * @return The destination object.
        **/
        merge<P, T, S1, Value, Result>(
            object: T,
            s1: S1,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.merge
        **/
        merge<P, T, S1, S2, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.merge
        **/
        merge<P, T, S1, S2, S3, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            s3: S3,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;

        /**
        * @see _.merge
        **/
        merge<P, T, S1, S2, S3, S4, Value, Result>(
            object: T,
            s1: S1,
            s2: S2,
            s3: S3,
            s4: S4,
            callback?: (objectValue: Value, sourceValue: Value) => Value,
            thisArg?: any): Result;
    }

    //_.omit
    interface LoDashStatic {
        /**
        * Creates a shallow clone of object excluding the specified properties. Property names may be
        * specified as individual arguments or as arrays of property names. If a callback is provided
        * it will be executed for each property of object omitting the properties the callback returns
        * truey for. The callback is bound to thisArg and invoked with three arguments; (value, key,
        * object).
        * @param object The source object.
        * @param keys The properties to omit.
        * @return An object without the omitted properties.
        **/
        omit<Omitted, T>(
            object: T,
            ...keys: string[]): Omitted;

        /**
        * @see _.omit
        **/
        omit<Omitted, T>(
            object: T,
            keys: string[]): Omitted;

        /**
        * @see _.omit
        **/
        omit<Omitted, T>(
            object: T,
            callback: ObjectIterator<any, boolean>,
            thisArg?: any): Omitted;
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.omit
        **/
        omit<Omitted>(
            ...keys: string[]): LoDashObjectWrapper<Omitted>;

        /**
        * @see _.omit
        **/
        omit<Omitted>(
            keys: string[]): LoDashObjectWrapper<Omitted>;

        /**
        * @see _.omit
        **/
        omit<Omitted>(
            callback: ObjectIterator<any, boolean>,
            thisArg?: any): LoDashObjectWrapper<Omitted>;
    }

    //_.pairs
    interface LoDashStatic {
        /**
        * Creates a two dimensional array of an object’s key-value pairs,
        * i.e. [[key1, value1], [key2, value2]].
        * @param object The object to inspect.
        * @return Aew array of key-value pairs.
        **/
        pairs(object: any): any[][];
    }

    interface LoDashObjectWrapper<T> {
        /**
        * @see _.pairs
        **/
        pairs(): LoDashArrayWrapper<any[]>;
    }

    //_.picks
    interface LoDashStatic {
        /**
        * Creates a shallow clone of object composed of the specified properties. Property names may be
        * specified as individual arguments or as arrays of property names. If a callback is provided
        * it will be executed for each property of object picking the properties the callback returns
        * truey for. The callback is bound to thisArg and invoked with three arguments; (value, key,
        * object).
        * @param object Object to strip unwanted key/value pairs.
        * @param keys Property names to pick
        * @return An object composed of the picked properties.
        **/
        pick<Picked, T>(
            object: T,
            ...keys: string[]): Picked;

        /**
        * @see _.pick
        **/
        pick<Picked, T>(
            object: T,
            keys: string[]): Picked;

        /**
        * @see _.pick
        **/
        pick<Picked, T>(
            object: T,
            callback: ObjectIterator<any, boolean>,
            thisArg?: any): Picked;
    }

    //_.transform
    interface LoDashStatic {
        /**
        * An alternative to _.reduce this method transforms object to a new accumulator object which is
        * the result of running each of its elements through a callback, with each callback execution
        * potentially mutating the accumulator object. The callback is bound to thisArg and invoked with
        * four arguments; (accumulator, value, key, object). Callbacks may exit iteration early by
        * explicitly returning false.
        * @param collection The collection to iterate over.
        * @param callback The function called per iteration.
        * @param accumulator The custom accumulator value.
        * @param thisArg The this binding of callback.
        * @return The accumulated value.
        **/
        transform<T, Acc>(
            collection: Array<T>,
            callback: MemoVoidIterator<T, Acc>,
            accumulator: Acc,
            thisArg?: any): Acc;

        /**
        * @see _.transform
        **/
        transform<T, Acc>(
            collection: List<T>,
            callback: MemoVoidIterator<T, Acc>,
            accumulator: Acc,
            thisArg?: any): Acc;

        /**
        * @see _.transform
        **/
        transform<T, Acc>(
            collection: Dictionary<T>,
            callback: MemoVoidIterator<T, Acc>,
            accumulator: Acc,
            thisArg?: any): Acc;

        /**
        * @see _.transform
        **/
        transform<T, Acc>(
            collection: Array<T>,
            callback?: MemoVoidIterator<T, Acc>,
            thisArg?: any): Acc;

        /**
        * @see _.transform
        **/
        transform<T, Acc>(
            collection: List<T>,
            callback?: MemoVoidIterator<T, Acc>,
            thisArg?: any): Acc;

        /**
        * @see _.transform
        **/
        transform<T, Acc>(
            collection: Dictionary<T>,
            callback?: MemoVoidIterator<T, Acc>,
            thisArg?: any): Acc;
    }

    //_.values
    interface LoDashStatic {
        /**
        * Creates an array composed of the own enumerable property values of object.
        * @param object The object to inspect.
        * @return Returns an array of property values.
        **/
        values(object: any): any[];
    }

    /*************
     * Utilities *
     *************/
    //_.escape
    interface LoDashStatic {
        /**
        * Converts the characters &, <, >, ", and ' in string to their corresponding HTML entities.
        * @param string The string to escape.
        * @return The escaped string.
        **/
        escape(str: string): string;
    }

    //_.identity
    interface LoDashStatic {
        /**
        * This method returns the first argument provided to it.
        * @param value Any value.
        * @return value.
        **/
        identity<T>(value: T): T;
    }

    //_.mixin
    interface LoDashStatic {
        /**
        * Adds function properties of a source object to the lodash function and chainable wrapper.
        * @param object The object of function properties to add to lodash.
        **/
        mixin(object: Dictionary<(value: any) => any>): void;
    }

    //_.noConflict
    interface LoDashStatic {
        /**
        * Reverts the '_' variable to its previous value and returns a reference to the lodash function.
        * @return The lodash function.
        **/
        noConflict(): typeof lodash;
    }

    //_.parseInt
    interface LoDashStatic {
        /**
        * Converts the given value into an integer of the specified radix. If radix is undefined or 0 a
        * radix of 10 is used unless the value is a hexadecimal, in which case a radix of 16 is used.
        *
        * Note: This method avoids differences in native ES3 and ES5 parseInt implementations. See
        * http://es5.github.io/#E.
        * @param value The value to parse.
        * @param radix The radix used to interpret the value to parse.
        * @return The new integer value.
        **/
        parseInt(value: string): number;
    }


    //_.property
    interface LoDashStatic {
        /**
         * # Ⓢ
         * Creates a "_.pluck" style function, which returns the key value of a given object.
         * @param key (string)
         * @return the value of that key on the object
         **/
        property<T,RT>(key: string): (obj: T) => RT;
    }

    //_.random
    interface LoDashStatic {
        /**
        * Produces a random number between min and max (inclusive). If only one argument is provided a
        * number between 0 and the given number will be returned. If floating is truey or either min or
        * max are floats a floating-point number will be returned instead of an integer.
        * @param max The maximum possible value.
        * @param floating Specify returning a floating-point number.
        * @return A random number.
        **/
        random(max: number, floating?: boolean): number;

        /**
        * @see _.random
        * @param min The minimum possible value.
        * @return A random number between `min` and `max`.
        **/
        random(min: number, max: number, floating?: boolean): number;
    }

    //_.result
    interface LoDashStatic {
        /**
        * Resolves the value of property on object. If property is a function it will be invoked with
        * the this binding of object and its result returned, else the property value is returned. If
        * object is falsey then undefined is returned.
        * @param object The object to inspect.
        * @param property The property to get the value of.
        * @return The resolved value.
        **/
        result(object: any, property: string): any;
    }

    //_.runInContext
    interface LoDashStatic {
        /**
        * Create a new lodash function using the given context object.
        * @param context The context object
        * @returns The lodash function.
        **/
        runInContext(context: any): typeof lodash;
    }

    //_.template
    interface LoDashStatic {
        /**
        * A micro-templating method that handles arbitrary delimiters, preserves whitespace, and
        * correctly escapes quotes within interpolated code.
        *
        * Note: In the development build, _.template utilizes sourceURLs for easier debugging. See
        * http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
        *
        * For more information on precompiling templates see:
        * http://lodash.com/#custom-builds
        *
        * For more information on Chrome extension sandboxes see:
        * http://developer.chrome.com/stable/extensions/sandboxingEval.html
        * @param text The template text.
        * @param data The data object used to populate the text.
        * @param options The options object.
        * @param options.escape The "escape" delimiter.
        * @param options.evaluate The "evaluate" delimiter.
        * @param options.import An object to import into the template as local variables.
        * @param options.interpolate The "interpolate" delimiter.
        * @param sourceURL The sourceURL of the template’s compiled source.
        * @param variable The data object variable name.
        * @return Returns the compiled Lo-Dash HTML template or a TemplateExecutor if no data is passed.
        **/
        template(
            text: string): TemplateExecutor;

        /**
        * @see _.template
        **/
        template(
            text: string,
            data: any,
            options?: TemplateSettings,
            sourceURL?: string,
            variable?: string): any /* string or TemplateExecutor*/;
    }

    interface TemplateExecutor {
        (...data: any[]): string;
        source: string;
    }

    //_.times
    interface LoDashStatic {
        /**
        * Executes the callback n times, returning an array of the results of each callback execution.
        * The callback is bound to thisArg and invoked with one argument; (index).
        * @param n The number of times to execute the callback.
        * @param callback The function called per iteration.
        * @param thisArg The this binding of callback.
        **/
        times<TResult>(
            n: number,
            callback: (num: number) => TResult,
            context?: any): TResult[];
    }

    //_.unescape
    interface LoDashStatic {
        /**
        * The inverse of _.escape this method converts the HTML entities &amp;, <, &gt;, &quot;, and
        * &#39; in string to their corresponding characters.
        * @param string The string to unescape.
        * @return The unescaped string.
        **/
        unescape(
            string: string): string;
    }

    //_.uniqueId
    interface LoDashStatic {
        /**
        * Generates a unique ID. If prefix is provided the ID will be appended to it.
        * @param prefix The value to prefix the ID with.
        * @return Returns the unique ID.
        **/
        uniqueId(prefix?: string): string;
    }

    //_.noop
    interface LoDashStatic {
        /**
         * A no-operation function.
         **/
        noop(): void;
    }

    //_.constant
    interface LoDashStatic {
        /**
         * Creates a function that returns value..
         **/
        constant<T>(value: T): () => T;
    }

    //_.create
    interface LoDashStatic {
        /**
         * Creates an object that inherits from the given prototype object. If a properties object is provided its own enumerable properties are assigned to the created object.
         * @param prototype The object to inherit from.
         * @param properties The properties to assign to the object.
         */
        create<T>(prototype: Object, properties?: Object): Object;
    }

    interface ListIterator<T, TResult> {
        (value: T, index: number, list: T[]): TResult;
    }

    interface ObjectIterator<T, TResult> {
        (element: T, key: string, list: any): TResult;
    }

    interface MemoVoidIterator<T, TResult> {
        (prev: TResult, curr: T, indexOrKey: any, list?: T[]): void;
    }
    interface MemoIterator<T, TResult> {
        (prev: TResult, curr: T, indexOrKey: any, list?: T[]): TResult;
    }
    /*
    interface MemoListIterator<T, TResult> {
        (prev: TResult, curr: T, index: number, list?: T[]): TResult;
    }
    interface MemoObjectIterator<T, TResult> {
        (prev: TResult, curr: T, index: string, object?: Dictionary<T>): TResult;
    }
    */

    //interface Collection<T> {}

    // Common interface between Arrays and jQuery objects
    interface List<T> {
        [index: number]: T;
        length: number;
    }

    interface Dictionary<T> {
        [index: string]: T;
    }
}

declare module "lodash" {
    export = _;
}