diff --git a/icepick/icepick-tests.ts b/icepick/icepick-tests.ts
new file mode 100644
index 0000000000..350e5f2dc8
--- /dev/null
+++ b/icepick/icepick-tests.ts
@@ -0,0 +1,177 @@
+///
+///
+
+
+import i = require("icepick");
+
+"use strict"; // so attempted modifications of frozen objects will throw errors
+
+// freeze(collection)
+{
+ let coll = {
+ a: "foo",
+ b: [1, 2, 3],
+ c: {
+ d: "bar"
+ }
+ };
+
+ i.freeze(coll);
+}
+
+// thaw(collection)
+class Foo {}
+
+{
+ let coll = i.freeze({ a: "foo", b: [1, 2, 3], c: { d: "bar" }, e: new Foo() });
+ let thawed = i.thaw(coll);
+}
+
+// assoc(collection, key, value)
+{
+ let coll = { a: 1, b: 2 };
+ let newColl = i.assoc(coll, "b", 3); // {a: 1, b: 3}
+
+ let arr = ["a", "b", "c"];
+ let newArr = i.assoc(arr, 2, "d"); // ["a", "b", "d"]
+}
+
+// alias: set(collection, key, value)
+{
+ let coll = { a: 1, b: 2 };
+ let newColl = i.set(coll, "b", 3); // {a: 1, b: 3}
+
+ let arr = ["a", "b", "c"];
+ let newArr = i.set(arr, 2, "d"); // ["a", "b", "d"]
+}
+
+// dissoc(collection, key)
+{
+ let coll = { a: 1, b: 2, c: 3 };
+ let newColl = i.dissoc(coll, "b"); // {a: 1, c: 3}
+
+ let arr = ["a", "b", "c"];
+ let newArr = i.dissoc(arr, 2); // ["a", , "c"]
+}
+
+// alias: unset(collection, key)
+{
+ let coll = { a: 1, b: 2, c: 3 };
+ let newColl = i.unset(coll, "b"); // {a: 1, c: 3}
+
+ let arr = ["a", "b", "c"];
+ let newArr = i.unset(arr, 2); // ["a", , "c"]
+}
+
+// assocIn(collection, path, value)
+{
+ let coll = {
+ a: "foo",
+ b: [1, 2, 3],
+ c: {
+ d: "bar"
+ }
+ };
+
+ let newColl = i.assocIn(coll, ["c", "d"], "baz");
+
+ let coll2 = {};
+ let newColl2 = i.assocIn(coll2, ["a", "b", "c"], 1);
+}
+
+// alias: setIn(collection, path, value)
+{
+ let coll = {
+ a: "foo",
+ b: [1, 2, 3],
+ c: {
+ d: "bar"
+ }
+ };
+
+ let newColl = i.setIn(coll, ["c", "d"], "baz");
+
+ let coll2 = {};
+ let newColl2 = i.setIn(coll2, ["a", "b", "c"], 1);
+}
+
+// getIn(collection, path)
+{
+ let coll = i.freeze([
+ { a: 1 },
+ { b: 2 }
+ ]);
+
+ let result = i.getIn(coll, [1, "b"]); // 2
+}
+
+// updateIn(collection, path, callback)
+{
+ let coll = i.freeze([
+ { a: 1 },
+ { b: 2 }
+ ]);
+
+ let newColl = i.updateIn(coll, [1, "b"], function(val: number) {
+ return val * 2;
+ }); // [ {a: 1}, {b: 4} ]
+}
+
+// assign(coll1, coll2, ...)
+{
+ let obj1 = { a: 1, b: 2, c: 3 };
+ let obj2 = { c: 4, d: 5 };
+
+ let result = i.assign(obj1, obj2); // {a: 1, b: 2, c: 4, d: 5}
+}
+
+// merge(target, source)
+{
+ let defaults = { a: 1, c: { d: 1, e: [1, 2, 3], f: { g: 1 } } };
+ let obj = { c: { d: 2, e: [2], f: null as any } };
+
+ let result1 = i.merge(defaults, obj); // {a: 1, c: {d: 2, e: [2]}, f: null}
+
+ let obj2 = { c: { d: 2 } };
+ let result2 = i.merge(result1, obj2);
+
+ (result1 === result2); // true
+}
+
+// arrays
+{
+ var a = [1];
+ a = i.push(a, 2); // [1, 2];
+ a = i.unshift(a, 0); // [0, 1, 2];
+ a = i.pop(a); // [0, 1];
+ a = i.shift(a); // [1];
+}
+{
+ i.map(function(v) { return v * 2 }, [1, 2, 3]); // [2, 4, 6]
+
+ var removeEvens = _.partial(i.filter, function(v: number) { return v % 2; });
+
+ removeEvens([1, 2, 3]); // [1, 3]
+}
+{
+ var arr = i.freeze([{ a: 1 }, { b: 2 }]);
+
+ //ECMAScript 2015
+ //arr.find(function(item) { return item.b != null; }); // {b: 2}
+}
+
+// chain(coll) - not defined
+{
+ let o = {
+ a: [1, 2, 3],
+ b: { c: 1 },
+ d: 4
+ };
+
+ let result = i.chain(o)
+ .assocIn(["a", 2], 4)
+ .merge({ b: { c: 2, c2: 3 } })
+ .assoc("e", 2)
+ .dissoc("d")
+ .value();
+}
diff --git a/icepick/icepick.d.ts b/icepick/icepick.d.ts
new file mode 100644
index 0000000000..85bbf0ae3d
--- /dev/null
+++ b/icepick/icepick.d.ts
@@ -0,0 +1,72 @@
+// Type definitions for icepick v1.1.0
+// Project: https://github.com/aearly/icepick
+// Definitions by: Nathan Brown
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+declare module "icepick" {
+ export function freeze(collection: T): T;
+ export function thaw(collection: T): T;
+ export function assoc(collection: T, key: number | string, value: any): T;
+ export function dissoc(collection: T, key: number | string): T;
+ export function assocIn(collection: T, path: Array, value: any): T;
+ export function getIn(collection: any, path: Array): Result;
+ export function updateIn(collection: T, path: Array, callback: (value: V) => V): T;
+
+ export {assoc as set};
+ export {dissoc as unset};
+ export {assocIn as setIn};
+
+ export function assign(target: T): T;
+ export function assign(target: T, source1: S1): (T & S1);
+ export function assign(target: T, s1: S1, s2: S2): (T & S1 & S2);
+ export function assign(target: T, s1: S1, s2: S2, s3: S3): (T & S1 & S2 & S3);
+ export function assign(target: T, s1: S1, s2: S2, s3: S3, s4: S4): (T & S1 & S2 & S3 & S4);
+
+ export {assign as extend};
+
+ export function merge(target: T, source: S1): (T & S1);
+
+ export function push(array: T[], element: T): T[];
+ export function pop(array: T[]): T[];
+ export function shift(array: T[]): T[];
+ export function unshift(array: T[], element: T): T[];
+ export function reverse(array: T[]): T[];
+ export function sort(array: T[], compareFunction?: (a:T, b:T) => number): T[];
+ export function splice(array: T[], start: number, deleteCount: number, ...items: T[]): T[];
+ export function slice(array: T[], begin?: number, end?: number): T[];
+
+ export function map(fn: (value: T) => U, array: T[]): U[];
+ export function filter(fn: (value: T) => boolean, array: T[]): T[];
+
+ interface IcepickWrapper {
+ value(): T;
+
+ freeze(): IcepickWrapper;
+ thaw(): IcepickWrapper;
+
+ assoc(key: number | string, value: any): IcepickWrapper;
+ set(key: number | string, value: any): IcepickWrapper;
+
+ dissoc(key: number | string): IcepickWrapper;
+ unset(key: number | string): IcepickWrapper;
+
+ assocIn(path: Array, value: any): IcepickWrapper;
+ setIn(path: Array, value: any): IcepickWrapper;
+
+ getIn(collection: any, path: Array): IcepickWrapper;
+ updateIn(collection: T, path: Array, callback: (value: V) => V): IcepickWrapper;
+
+ assign(source1: S1): IcepickWrapper;
+ assign(s1: S1, s2: S2): IcepickWrapper;
+ assign(s1: S1, s2: S2, s3: S3): IcepickWrapper;
+ assign(s1: S1, s2: S2, s3: S3, s4: S4): IcepickWrapper;
+ extend(source1: S1): IcepickWrapper;
+ extend(s1: S1, s2: S2): IcepickWrapper;
+ extend(s1: S1, s2: S2, s3: S3): IcepickWrapper;
+ extend(s1: S1, s2: S2, s3: S3, s4: S4): IcepickWrapper;
+
+ merge(source: S1): IcepickWrapper;
+ }
+
+ export function chain(target: T): IcepickWrapper;
+}