diff --git a/README.md b/README.md
index b2e60d65a..2d552bfc1 100755
--- a/README.md
+++ b/README.md
@@ -159,6 +159,7 @@ List of Definitions
* [Levelup](https://github.com/rvagg/node-levelup) (by [Bret Little](https://github.com/blittle))
* [linq.js](http://linqjs.codeplex.com/) (by [Marcin Najder](https://github.com/marcinnajder))
* [Livestamp.js](https://github.com/mattbradley/livestampjs) (by [Vincent Bortone](https://github.com/vbortone))
+* [Lodash](http://lodash.com/) (by [Brian Zengel](https://github.com/bczengel))
* [Logg](https://github.com/dpup/node-logg) (by [Bret Little](https://github.com/blittle))
* [Marked](https://github.com/chjj/marked) (by [William Orr](https://github.com/worr))
* [mCustomScrollbar](https://github.com/malihu/malihu-custom-scrollbar-plugin) (by [Sarah Williams] (https://github.com/flurg))
@@ -243,7 +244,6 @@ Requested Definitions
* [google.visualizations](https://developers.google.com/chart/)
* [Prelude.ls](http://gkz.github.com/prelude-ls/)
* [MooTools](http://mootools.net/)
-* [Lo-Dash](http://lodash.com/)
* [java](https://github.com/nearinfinity/node-java)
* [SVG.js](http://www.svgjs.com/)
diff --git a/lodash/lodash-tests.ts b/lodash/lodash-tests.ts
new file mode 100644
index 000000000..400d8664a
--- /dev/null
+++ b/lodash/lodash-tests.ts
@@ -0,0 +1,929 @@
+///
+
+declare var $: any, jQuery: any;
+
+interface IFoodOrganic {
+ name: string;
+ organic: boolean;
+}
+
+interface IFoodType {
+ name: string;
+ type: string;
+}
+
+interface IFoodCombined {
+ name: string;
+ organic: boolean;
+ type: string;
+}
+
+interface IStoogesQuote {
+ name: string;
+ quotes: string[];
+}
+
+interface IStoogesAge {
+ name: string;
+ age: number;
+}
+
+interface IStoogesCombined {
+ name: string;
+ age: number;
+ quotes: string[];
+}
+
+interface IKey {
+ dir: string;
+ code: number;
+}
+
+var foodsOrganic: IFoodOrganic[] = [
+ { name: 'banana', organic: true },
+ { name: 'beet', organic: false },
+];
+var foodsType: IFoodType[] = [
+ { name: 'apple', type: 'fruit' },
+ { name: 'banana', type: 'fruit' },
+ { name: 'beet', type: 'vegetable' }
+];
+var foodsCombined: IFoodCombined[] = [
+ { 'name': 'apple', 'organic': false, 'type': 'fruit' },
+ { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
+];
+
+var stoogesQuotes: IStoogesQuote[] = [
+ { 'name': 'curly', 'quotes': ['Oh, a wise guy, eh?', 'Poifect!'] },
+ { 'name': 'moe', 'quotes': ['Spread out!', 'You knucklehead!'] }
+];
+var stoogesAges: IStoogesAge[] = [
+ { 'name': 'moe', 'age': 40 },
+ { 'name': 'larry', 'age': 50 }
+];
+
+var stoogesCombined: IStoogesCombined[] = [
+ { 'name': 'curly', 'age': 30, 'quotes': ['Oh, a wise guy, eh?', 'Poifect!'] },
+ { 'name': 'moe', 'age': 40, 'quotes': ['Spread out!', 'You knucklehead!'] }
+];
+
+var keys: IKey[] = [
+ { 'dir': 'left', 'code': 97 },
+ { 'dir': 'right', 'code': 100 }
+];
+
+class Dog {
+ constructor(public name: string) {}
+
+ public bark() {
+ console.log('Woof, woof!');
+ }
+}
+
+var result : any;
+
+/*************
+ * Chaining *
+ *************/
+result = <_.LoDashWrapper>_('test');
+result = <_.LoDashWrapper>_(1);
+result = <_.LoDashWrapper>_(true);
+result = <_.LoDashArrayWrapper>_(['test1', 'test2']);
+result = <_.LoDashObjectWrapper<_.Dictionary>>_({'key1': 'test1', 'key2': 'test2'});
+
+result = <_.LoDashWrapper>_.chain('test');
+result = <_.LoDashWrapper>_('test').chain();
+result = <_.LoDashWrapper>_.chain(1);
+result = <_.LoDashWrapper>_(1).chain();
+result = <_.LoDashWrapper>_.chain(true);
+result = <_.LoDashWrapper>_(true).chain();
+result = <_.LoDashArrayWrapper>_.chain(['test1', 'test2']);
+result = <_.LoDashArrayWrapper>_(['test1', 'test2']).chain();
+result = <_.LoDashObjectWrapper<_.Dictionary>>_.chain({'key1': 'test1', 'key2': 'test2'});
+result = <_.LoDashObjectWrapper<_.Dictionary>>_({'key1': 'test1', 'key2': 'test2'}).chain();
+
+//Wrapped array shortcut methods
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).concat(5, 6);
+result = <_.LoDashWrapper>_([1, 2, 3, 4]).join(',');
+result = <_.LoDashWrapper>_([1, 2, 3, 4]).pop();
+_([1, 2, 3, 4]).push(5, 6, 7);
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).reverse();
+result = <_.LoDashWrapper>_([1, 2, 3, 4]).shift();
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).slice(1, 2);
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).slice(2);
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).sort((a, b) => 1);
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).splice(1);
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).splice(1, 2, 5, 6);
+result = <_.LoDashWrapper>_([1, 2, 3, 4]).unshift(5, 6);
+
+result = _.tap([1, 2, 3, 4], function(array) { console.log(array); });
+result = <_.LoDashWrapper>_('test').tap(function(value) { console.log(value); });
+result = <_.LoDashArrayWrapper>_([1, 2, 3, 4]).tap(function(array) { console.log(array); });
+result = <_.LoDashObjectWrapper<_.Dictionary>>_({'key1': 'test1', 'key2': 'test2'}).tap(function(array) { console.log(array); });
+
+result = _('test').toString();
+result = _([1, 2, 3]).toString();
+result = _({'key1': 'test1', 'key2': 'test2'}).toString();
+
+result = _('test').valueOf();
+result = _([1, 2, 3]).valueOf();
+result = <_.Dictionary>_({'key1': 'test1', 'key2': 'test2'}).valueOf();
+
+result = _('test').value();
+result = _([1, 2, 3]).value();
+result = <_.Dictionary>_({'key1': 'test1', 'key2': 'test2'}).value();
+
+// /*************
+// * Arrays *
+// *************/
+result = _.compact([0, 1, false, 2, '', 3]);
+ result = <_.LoDashArrayWrapper>_([0, 1, false, 2, '', 3]).compact();
+
+result = _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+ result = <_.LoDashArrayWrapper>_([1, 2, 3, 4, 5]).difference([5, 2, 10]);
+
+result = _.rest([1, 2, 3]);
+result = _.rest([1, 2, 3], 2);
+result = _.rest([1, 2, 3], (num) => num < 3)
+result = _.rest(foodsOrganic, 'test');
+result = _.rest(foodsType, { 'type': 'value' });
+
+result = _.drop([1, 2, 3]);
+result = _.drop([1, 2, 3], 2);
+result = _.drop([1, 2, 3], (num) => num < 3)
+result = _.drop(foodsOrganic, 'test');
+result = _.drop(foodsType, { 'type': 'value' });
+
+result = _.tail([1, 2, 3])
+result = _.tail([1, 2, 3], 2)
+result = _.tail([1, 2, 3], (num) => num < 3)
+result = _.tail(foodsOrganic, 'test')
+result = _.tail(foodsType, { 'type': 'value' })
+
+result = _.findIndex(['apple', 'banana', 'beet'], function(f) {
+ return /^b/.test(f);
+});
+result = _.findIndex(['apple', 'banana', 'beet'], 'apple');
+result = _.findIndex([{ food: 'apple' }, { food: 'banana' }, { food: 'beet' }], { food: 'apple'});
+
+result = _.findLastIndex(['apple', 'banana', 'beet'], function(f: string) {
+ return /^b/.test(f);
+});
+result = _.findLastIndex(['apple', 'banana', 'beet'], 'apple');
+result = _.findLastIndex([{ food: 'apple' }, { food: 'banana' }, { food: 'beet' }], { food: 'apple'});
+
+result = _.first([1, 2, 3]);
+result = _.first([1, 2, 3], 2);
+result = _.first([1, 2, 3], function(num) {
+ return num < 3;
+});
+result = _.first(foodsOrganic, 'organic');
+result = _.first(foodsType, { 'type': 'fruit' });
+
+ result = _.head([1, 2, 3]);
+ result = _.head([1, 2, 3], 2);
+ result = _.head([1, 2, 3], function(num) {
+ return num < 3;
+ });
+ result = _.head(foodsOrganic, 'organic');
+ result = _.head(foodsType, { 'type': 'fruit' });
+
+ result = _.take([1, 2, 3]);
+ result = _.take([1, 2, 3], 2);
+ result = _.take([1, 2, 3], (num) => num < 3);
+ result = _.take(foodsOrganic, 'organic');
+ result = _.take(foodsType, { 'type': 'fruit' });
+
+result = _.flatten([1, [2], [3, [[4]]]]);
+result = _.flatten([1, [2], [3, [[4]]]], true);
+var result: any
+result = _.flatten(stoogesQuotes, 'quotes');
+
+ result = <_.LoDashArrayWrapper>_([1, [2], [3, [[4]]]]).flatten();
+ result = <_.LoDashArrayWrapper>_([1, [2], [3, [[4]]]]).flatten(true);
+ result = <_.LoDashArrayWrapper>_(stoogesQuotes).flatten('quotes');
+
+result = _.indexOf([1, 2, 3, 1, 2, 3], 2);
+result = _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+result = _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+
+result = _.initial([1, 2, 3]);
+result = _.initial([1, 2, 3], 2);
+result = _.initial([1, 2, 3], function(num) {
+ return num > 1;
+});
+result = _.initial(foodsOrganic, 'organic');
+result = _.initial(foodsType, { 'type': 'vegetable' });
+
+result = _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+
+result = _.last([1, 2, 3]);
+result = _.last([1, 2, 3], 2);
+result = _.last([1, 2, 3], function(num) {
+ return num > 1;
+});
+result = _.last(foodsOrganic, 'organic');
+result = _.last(foodsType, { 'type': 'vegetable' });
+
+result = _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+result = _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+
+result = <{[key: string]: any}>_.zipObject(['moe', 'larry'], [30, 40]);
+ result = <{[key: string]: any}>_.object(['moe', 'larry'], [30, 40]);
+
+result = _.pull([1, 2, 3, 1, 2, 3], 2, 3);
+
+result = _.range(10);
+result = _.range(1, 11);
+result = _.range(0, 30, 5);
+result = _.range(0, -10, -1);
+result = _.range(1, 4, 0);
+result = _.range(0);
+
+result = _.remove([1, 2, 3, 4, 5, 6], function(num: number) { return num % 2 == 0; });
+result = _.remove(foodsOrganic, 'organic');
+result = _.remove(foodsType, { 'type': 'vegetable'});
+
+result = _.sortedIndex([20, 30, 50], 40);
+result = _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+var sortedIndexDict = {
+ 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+};
+result = _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+ return sortedIndexDict.wordToNumber[word];
+});
+result = _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+ return this.wordToNumber[word];
+}, sortedIndexDict);
+
+result = _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+
+result = _.uniq([1, 2, 1, 3, 1]);
+result = _.uniq([1, 1, 2, 2, 3], true);
+result = _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) {
+ return letter.toLowerCase();
+});
+result = _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+result = <{x: number;}[]>_.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+
+ result = _.unique([1, 2, 1, 3, 1]);
+ result = _.unique([1, 1, 2, 2, 3], true);
+ result = _.unique(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) {
+ return letter.toLowerCase();
+ });
+ result = _.unique([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+ result = <{x: number;}[]>_.unique([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+
+result = _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+
+result = _.zip(['moe', 'larry'], [30, 40], [true, false]);
+ result = _.unzip(['moe', 'larry'], [30, 40], [true, false]);
+
+// /* *************
+// * Collections *
+// ************* */
+
+result = _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+result = _.at(['moe', 'larry', 'curly'], 0, 2);
+
+result = _.contains([1, 2, 3], 1);
+result = _.contains([1, 2, 3], 1, 2);
+result = _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+result = _.contains('curly', 'ur');
+
+ result = _.include([1, 2, 3], 1);
+ result = _.include([1, 2, 3], 1, 2);
+ result = _.include({ 'name': 'moe', 'age': 40 }, 'moe');
+ result = _.include('curly', 'ur');
+
+result = <_.Dictionary>_.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+result = <_.Dictionary>_.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+result = <_.Dictionary>_.countBy(['one', 'two', 'three'], 'length');
+
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_([4.3, 6.1, 6.4]).countBy(function(num) { return Math.floor(num); });
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_([4.3, 6.1, 6.4]).countBy(function(num) { return this.floor(num); }, Math);
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_(['one', 'two', 'three']).countBy('length');
+
+result = _.every([true, 1, null, 'yes'], Boolean);
+result = _.every(stoogesAges, 'age');
+result = _.every(stoogesAges, { 'age': 50 });
+
+ result = _.all([true, 1, null, 'yes'], Boolean);
+ result = _.all(stoogesAges, 'age');
+ result = _.all(stoogesAges, { 'age': 50 });
+
+result = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+result = _.filter(foodsCombined, 'organic');
+result = _.filter(foodsCombined, { 'type': 'fruit' });
+
+ result = _([1, 2, 3, 4, 5, 6]).filter(function(num) { return num % 2 == 0; });
+ result = _(foodsCombined).filter('organic');
+ result = _(foodsCombined).filter({ 'type': 'fruit' });
+
+ result = _.select([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ result = _.select(foodsCombined, 'organic');
+ result = _.select(foodsCombined, { 'type': 'fruit' });
+
+ result = _([1, 2, 3, 4, 5, 6]).select(function(num) { return num % 2 == 0; });
+ result = _(foodsCombined).select('organic');
+ result = _(foodsCombined).select({ 'type': 'fruit' });
+
+result = _.find([1, 2, 3, 4], function(num) {
+ return num % 2 == 0;
+});
+result = _.find(foodsCombined, { 'type': 'vegetable' });
+result = _.find(foodsCombined, 'organic');
+
+ result = _.detect([1, 2, 3, 4], function(num) {
+ return num % 2 == 0;
+ });
+ result = _.detect(foodsCombined, { 'type': 'vegetable' });
+ result = _.detect(foodsCombined, 'organic');
+
+ result = _.findWhere([1, 2, 3, 4], function(num) {
+ return num % 2 == 0;
+ });
+ result = _.findWhere(foodsCombined, { 'type': 'vegetable' });
+ result = _.findWhere(foodsCombined, 'organic');
+
+result = _.findLast([1, 2, 3, 4], function(num) {
+ return num % 2 == 0;
+});
+result = _.findLast(foodsCombined, { 'type': 'vegetable' });
+result = _.findLast(foodsCombined, 'organic');
+
+result = _.forEach([1, 2, 3], function(num) { console.log(num); });
+result = <_.Dictionary>_.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+
+ result = _.each([1, 2, 3], function(num) { console.log(num); });
+ result = <_.Dictionary>_.each({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+
+ result = <_.LoDashArrayWrapper>_([1, 2, 3]).forEach(function(num) { console.log(num); });
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_({ 'one': 1, 'two': 2, 'three': 3 }).forEach(function(num) { console.log(num); });
+
+ result = <_.LoDashArrayWrapper>_([1, 2, 3]).each(function(num) { console.log(num); });
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_({ 'one': 1, 'two': 2, 'three': 3 }).each(function(num) { console.log(num); });
+
+result = _.forEachRight([1, 2, 3], function(num) { console.log(num); });
+result = <_.Dictionary>_.forEachRight({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+
+ result = _.eachRight([1, 2, 3], function(num) { console.log(num); });
+ result = <_.Dictionary>_.eachRight({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+
+ result = <_.LoDashArrayWrapper>_([1, 2, 3]).forEachRight(function(num) { console.log(num); });
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_({ 'one': 1, 'two': 2, 'three': 3 }).forEachRight(function(num) { console.log(num); });
+
+ result = <_.LoDashArrayWrapper>_([1, 2, 3]).eachRight(function(num) { console.log(num); });
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_({ 'one': 1, 'two': 2, 'three': 3 }).eachRight(function(num) { console.log(num); });
+
+result = <_.Dictionary>_.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+result = <_.Dictionary>_.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+result = <_.Dictionary>_.groupBy(['one', 'two', 'three'], 'length');
+
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_([4.2, 6.1, 6.4]).groupBy(function(num) { return Math.floor(num); });
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_([4.2, 6.1, 6.4]).groupBy(function(num) { return this.floor(num); }, Math);
+ result = <_.LoDashObjectWrapper<_.Dictionary>>_(['one', 'two', 'three']).groupBy('length');
+
+result = <_.Dictionary>_.indexBy(keys, 'dir');
+result = <_.Dictionary>_.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
+result = <_.Dictionary>_.indexBy(keys, function(key) { this.fromCharCode(key.code); }, String);
+
+result = _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+result = _.invoke([123, 456], String.prototype.split, '');
+
+result = _.map([1, 2, 3], function(num) { return num * 3; });
+result = _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+result = _.map(stoogesAges, 'name');
+
+ result = _.collect([1, 2, 3], function(num) { return num * 3; });
+ result = _.collect({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+ result = _.collect(stoogesAges, 'name');
+
+result = _.max([4, 2, 8, 6]);
+result = _.max(stoogesAges, function(stooge) { return stooge.age; });
+result = _.max(stoogesAges, 'age');
+
+result = _.min([4, 2, 8, 6]);
+result = _.min(stoogesAges, function(stooge) { return stooge.age; });
+result = _.min(stoogesAges, 'age');
+
+result = _.pluck(stoogesAges, 'name');
+
+result = _.reduce([1, 2, 3], function(sum: number, num: number) {
+ return sum + num;
+});
+result = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(r: any, num: number, key: string) {
+ r[key] = num * 3;
+ return r;
+}, {});
+
+ result = _.foldl([1, 2, 3], function(sum: number, num: number) {
+ return sum + num;
+ });
+ result = _.foldl({ 'a': 1, 'b': 2, 'c': 3 }, function(r: any, num: number, key: string) {
+ r[key] = num * 3;
+ return r;
+ }, {});
+
+ result = _.inject([1, 2, 3], function(sum: number, num: number) {
+ return sum + num;
+ });
+ result = _.inject({ 'a': 1, 'b': 2, 'c': 3 }, function(r: any, num: number, key: string) {
+ r[key] = num * 3;
+ return r;
+ }, {});
+
+result = _.reduceRight([[0, 1], [2, 3], [4, 5]], function(a: number[], b: number[]) { return a.concat(b); }, []);
+ result = _.foldr([[0, 1], [2, 3], [4, 5]], function(a: number[], b: number[]) { return a.concat(b); }, []);
+
+result = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+result = _.reject(foodsCombined, 'organic');
+result = _.reject(foodsCombined, { 'type': 'fruit' });
+
+result = _.sample([1, 2, 3, 4]);
+result = _.sample([1, 2, 3, 4], 2);
+
+result = _.shuffle([1, 2, 3, 4, 5, 6]);
+
+result = _.size([1, 2]);
+result = _.size({ 'one': 1, 'two': 2, 'three': 3 });
+result = _.size('curly');
+
+result = _.some([null, 0, 'yes', false], Boolean);
+result = _.some(foodsCombined, 'organic');
+result = _.some(foodsCombined, { 'type': 'meat' });
+
+ result = _.any([null, 0, 'yes', false], Boolean);
+ result = _.any(foodsCombined, 'organic');
+ result = _.any(foodsCombined, { 'type': 'meat' });
+
+result = _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+result = _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+result = _.sortBy(['banana', 'strawberry', 'apple'], 'length');
+
+(function(a: any, b: any, c: any, d: any){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+
+result = _.where(stoogesCombined, { 'age': 40 });
+result = _.where(stoogesCombined, { 'quotes': ['Poifect!'] });
+
+/*************
+ * Functions *
+ *************/
+var saves = ['profile', 'settings'];
+var asyncSave = (obj: any) => obj.done();
+var done: Function;
+
+done = _.after(saves.length, function() {
+ console.log('Done saving!');
+});
+
+_.forEach(saves, function(type) {
+ asyncSave({ 'type': type, 'complete': done });
+});
+
+done = _(saves.length).after(function() {
+ console.log('Done saving!');
+}).value();
+
+_.forEach(saves, function(type) {
+ asyncSave({ 'type': type, 'complete': done });
+});
+
+var funcBind = function (greeting: string) { return greeting + ' ' + this.name };
+var funcBind2: () => any = _.bind(funcBind, { 'name': 'moe' }, 'hi');
+funcBind2();
+
+var funcBind3: () => any = _(funcBind).bind({ 'name': 'moe' }, 'hi').value();
+funcBind3();
+
+var view = {
+ 'label': 'docs',
+ 'onClick': function() { console.log('clicked ' + this.label); }
+};
+
+view = _.bindAll(view);
+jQuery('#docs').on('click', view.onClick);
+
+view = _(view).bindAll().value();
+jQuery('#docs').on('click', view.onClick);
+
+var objectBindKey = {
+ 'name': 'moe',
+ 'greet': function(greeting: string) {
+ return greeting + ' ' + this.name;
+ }
+};
+
+var funcBindKey: Function = _.bindKey(objectBindKey, 'greet', 'hi');
+funcBindKey();
+
+objectBindKey.greet = function(greeting) {
+ return greeting + ', ' + this.name + '!';
+};
+
+funcBindKey();
+
+funcBindKey = _(objectBindKey).bindKey('greet', 'hi').value();
+funcBindKey();
+
+var realNameMap = {
+ 'curly': 'jerome'
+};
+
+var format = function(name: string) {
+ name = realNameMap[name.toLowerCase()] || name;
+ return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
+};
+
+var greet = function(formatted: string) {
+ return 'Hiya ' + formatted + '!';
+};
+
+result = _.compose(greet, format);
+result = <_.LoDashObjectWrapper>_(greet).compose(format);
+
+var createCallbackObj = { name: 'Joe' };
+result = <() => any>_.createCallback('name');
+result = <() => boolean>_.createCallback(createCallbackObj);
+result = <_.LoDashObjectWrapper<() => any>>_('name').createCallback();
+result = <_.LoDashObjectWrapper<() => boolean>>_(createCallbackObj).createCallback();
+
+result = _.curry(function(a, b, c) {
+ console.log(a + b + c);
+});
+
+result = <_.LoDashObjectWrapper>_(function(a, b, c) {
+ console.log(a + b + c);
+}).curry();
+
+declare var source: any;
+result = _.debounce(function() {}, 150);
+
+jQuery('#postbox').on('click', _.debounce(function() {}, 300, {
+ 'leading': true,
+ 'trailing': false
+}));
+
+source.addEventListener('message', _.debounce(function() {}, 250, {
+ 'maxWait': 1000
+}), false);
+
+result = <_.LoDashObjectWrapper>_(function() {}).debounce(150);
+
+jQuery('#postbox').on('click', <_.LoDashObjectWrapper>_(function() {}).debounce(300, {
+ 'leading': true,
+ 'trailing': false
+}));
+
+source.addEventListener('message', <_.LoDashObjectWrapper>_(function() {}).debounce(250, {
+ 'maxWait': 1000
+}), false);
+
+result = _.defer(function() { console.log('deferred'); });
+result = <_.LoDashWrapper