diff --git a/streamjs/README.md b/streamjs/README.md
new file mode 100644
index 0000000000..400e3bc412
--- /dev/null
+++ b/streamjs/README.md
@@ -0,0 +1,12 @@
+# StreamJS Type Definitions
+
+Note: this definition file is not for the StreamJS library available at http://streamjs.org but the one at
+http://winterbe.github.io/streamjs/ .
+
+Unsupported StreamJS function / method signatures:
+ * `Stream(collection)` (but `Stream.from(collection)` works)
+ * `Stream(string)` (but `Stream.from(string)` works)
+ * `Stream.empty()`
+ * `map(path)`
+ * `flatMap(path)`
+ * `Optional.empty()`
diff --git a/streamjs/streamjs-tests.ts b/streamjs/streamjs-tests.ts
new file mode 100644
index 0000000000..f911c8f522
--- /dev/null
+++ b/streamjs/streamjs-tests.ts
@@ -0,0 +1,152 @@
+///
+
+var numStream: Stream;
+numStream = Stream.of(1, 2, 3);
+numStream = Stream.range(1, 5);
+numStream = Stream.rangeClosed(1, 5);
+numStream = Stream.from([1, 2, 3]);
+Stream.generate(function() {
+ return 1;
+});
+Stream.generate(() => 1);
+
+numStream = Stream.iterate(1, (n) => n * 2);
+
+var comparator = (s1: string, s2: string) => 0;
+
+numStream = numStream.filter(n => n % 2 == 0);
+var strStream = numStream
+ .dropWhile((n: number) => n % 2 == 0)
+ .map(n => "number " + n)
+ .dropWhile(/^$/)
+ .limit(100)
+ .sorted()
+ .sort()
+ .sort("propName")
+ .sorted(comparator)
+ .sort(comparator)
+ .sorted("propName")
+ .shuffle()
+ .reverse()
+ .distinct()
+ .skip(5)
+ .peek(s => console.log(s))
+ .takeWhile(s => s.length < 5)
+ .takeWhile(/^aa.*$/)
+ .slice(5, 2)
+ ;
+strStream = Stream.from("foobar");
+var strArray = strStream.toArray();
+strArray = strStream.toList();
+strStream.each(s => console.log(s));
+strStream.filter(/^$/);
+strStream.forEach(s => console.log(s));
+var opt: Stream.Optional = strStream.findFirst();
+opt = strStream.findAny();
+opt = strStream.max();
+opt = strStream.max((s1, s2) => 0);
+opt = strStream.min();
+opt = strStream.min((s1, s2) => 0);
+
+var sum = numStream.sum();
+sum = numStream.sum("foo");
+var avg = numStream.average();
+avg = numStream.average("foo");
+avg = numStream.avg();
+avg = numStream.avg("foo");
+
+var count = numStream.count();
+count = numStream.size();
+
+var allMatch: boolean = numStream.allMatch(n => true);
+allMatch = strStream.allMatch(/^$/);
+
+var anyMatch: boolean = numStream.anyMatch(n => false);
+anyMatch = strStream.anyMatch(/^$/);
+
+var noneMatch: boolean = numStream.noneMatch(n => false);
+noneMatch = strStream.noneMatch(/^$/);
+
+sum = numStream.reduce(0, (n1, n2) => n1 + n2);
+opt = strStream.reduce((s1, s2) => s1 + s2);
+
+class MyList {
+ elems: any[];
+ name: string
+}
+
+var elems: any[];
+
+var myStream: Stream = Stream.from([new MyList, new MyList]);
+elems = myStream
+ .flatMap(list => list.elems)
+ .toArray();
+
+myStream = myStream.takeWhile({name: "foo"});
+myStream = myStream.dropWhile({name: "foo"});
+myStream = myStream.filter({name: "foo"});
+var myResult = myStream.min("name");
+myResult = myStream.max("name");
+var match: boolean = myStream.allMatch({name: "foo"});
+match = myStream.anyMatch({name: "foo"});
+
+numStream.collect({
+ supplier: () => 0,
+ accumulator: (n1, n2) => n1 + n2,
+ finisher: n => n
+});
+
+var groupingResult = myStream.groupBy(lst => lst.name);
+var elems = groupingResult["hello"].elems;
+groupingResult = myStream.groupingBy(lst => lst.name);
+groupingResult = myStream.groupBy("name");
+groupingResult = myStream.groupingBy("name");
+
+var mappingResult = myStream.toMap((lst) => lst.name, (e1: MyList, e2: MyList) => e2);
+var aMappingResult: MyList = mappingResult["a"];
+
+mappingResult = myStream.toMap("a");
+
+myStream.toMap(lst => lst.name);
+
+mappingResult = myStream.indexBy(lst => lst.name, (e1, e2) => e2);
+
+var partitionedNums: number[][] = numStream.partitioningBy(n => n % 2 == 0);
+partitionedNums = numStream.partitionBy(n => n % 2 == 0);
+
+var partitionedStrings : string[][] = strStream.partitionBy(/^a$/);
+partitionedStrings = strStream.partitioningBy(/^a$/);
+partitionedStrings = strStream.partitioningBy(5);
+partitionedStrings = strStream.partitionBy(5);
+
+var partitionedList: MyList[][] = myStream.partitionBy({name : "foo"});
+partitionedList = myStream.partitioningBy({name : "foo"});
+
+var s: string = numStream.joining();
+s = numStream.join();
+s = numStream.joining(", ");
+s = numStream.join(", ");
+s = numStream.joining({prefix: "{", delimiter: ", ", suffix: "}"});
+s = numStream.join({prefix: "{", delimiter: ", ", suffix: "}"});
+
+
+var iter = numStream.iterator();
+var n: number = iter.next();
+var done: boolean = iter.done;
+
+var optNum: Stream.Optional = Stream.Optional.of(2);
+optNum = Stream.Optional.ofNullable(null);
+
+var optStr: Stream.Optional = optNum.filter(n => n % 2 == 0)
+ .map(n => "number" + n)
+ .flatMap(n => Stream.Optional.of(n + 2))
+ ;
+
+var isPresent: boolean = optNum.isPresent();
+var num: number = optNum.get();
+optNum.ifPresent(n => console.log(n));
+var def: number = optNum.orElse(2);
+def = optNum.orElseGet(() => 3);
+def = optNum.orElseThrow("something went wrong");
+
+
diff --git a/streamjs/streamjs.d.ts b/streamjs/streamjs.d.ts
new file mode 100644
index 0000000000..59d8019f39
--- /dev/null
+++ b/streamjs/streamjs.d.ts
@@ -0,0 +1,165 @@
+// Type definitions for streamjs 1.5.0
+// Project: http://winterbe.github.io/streamjs/
+// Definitions by: Bence Eros
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+declare class Stream {
+ static from (elems: T[]): Stream;
+ static from(str: string): Stream;
+ static of(...elems: T[]): Stream;
+ static range (startInclusive: number, endExclusive: number): Stream;
+ static rangeClosed (startInclusive: number, endInclusive: number): Stream;
+ static generate (supplier: Stream.Supplier): Stream;
+ static iterate(seed: T, fn: Stream.Function): Stream;
+
+ anyMatch(predicate: Stream.Predicate): boolean;
+ anyMatch(regexp: RegExp): boolean;
+ anyMatch(sample: Stream.Sample): boolean;
+ allMatch(predicate: Stream.Predicate): boolean;
+ allMatch(regexp: RegExp): boolean;
+ allMatch(sample: Stream.Sample): boolean;
+ average(): number;
+ average(path: string): number;
+ avg(): number;
+ avg(path: string): number;
+ collect(collector: Stream.Collector): T;
+ count(): number;
+ distinct(): Stream;
+ dropWhile(predicate: Stream.Predicate): Stream;
+ dropWhile(regexp: RegExp): Stream;
+ dropWhile(sample: Stream.Sample): Stream;
+ each(consumer: Stream.Consumer): void;
+ filter(predicate: Stream.Predicate): Stream;
+ filter(regexp: RegExp): Stream;
+ filter(sample: Stream.Sample): Stream;
+ findAny(): Stream.Optional;
+ findFirst(): Stream.Optional;
+ forEach(consumer: Stream.Consumer): void;
+
+ groupBy(mapper: Stream.Function): Stream.GroupingResult;
+ groupBy(path: string): Stream.GroupingResult;
+ groupingBy(mapper: Stream.Function): Stream.GroupingResult;
+ groupingBy(path: string): Stream.GroupingResult;
+ indexBy(keyMapper: Stream.Function, mergeFunction?: Stream.Accumulator): Stream.Map;
+ map (mapper: Stream.Function): Stream;
+ max(): Stream.Optional;
+ max(comparator: Stream.Comparator): Stream.Optional;
+ max(path: string): Stream.Optional;
+ min(): Stream.Optional;
+ min(comparator: Stream.Comparator): Stream.Optional;
+ min(path: string): Stream.Optional;
+ noneMatch(predicate: (elem: T) => boolean): boolean;
+ noneMatch(regexp: RegExp): boolean;
+ flatMap (mapper: Stream.Function): Stream;
+ iterator(): Stream.Iterator;
+ joining(): string;
+ joining(delimiter: string): string;
+ joining(options: Stream.JoinOptions): string;
+ join(): string;
+ join(delimiter: string): string;
+ join(options: Stream.JoinOptions): string;
+ limit(limit: number): Stream;
+ partitioningBy(predicate: Stream.Predicate): T[][];
+ partitionBy(predicate: Stream.Predicate): T[][];
+ partitionBy(sample: Stream.Sample): T[][];
+ partitioningBy(regexp: RegExp): T[][];
+ partitionBy(regexp: RegExp): T[][];
+ partitioningBy(size: number): T[][];
+ partitionBy(size: number): T[][];
+ partitioningBy(sample: Stream.Sample): T[][];
+ peek(consumer: Stream.Consumer): Stream;
+ reduce(identity: T, accumulator: Stream.Accumulator): T;
+ reduce(accumulator: Stream.Accumulator): Stream.Optional;
+ reverse(): Stream;
+ size(): number;
+ sorted(): Stream;
+ sorted(comparator: Stream.Comparator): Stream;
+ sorted(path: string): Stream;
+ sort(): Stream;
+ sort(comparator: Stream.Comparator): Stream;
+ sort(path: string): Stream;
+ shuffle(): Stream;
+ skip(n: number): Stream;
+ slice(begin: number, end: number): Stream;
+ sum(): number;
+ sum(path: string): number;
+ takeWhile(predicate: Stream.Predicate): Stream;
+ takeWhile(regexp: RegExp): Stream;
+ takeWhile(sample: Stream.Sample): Stream;
+ toArray(): T[];
+ toList(): T[];
+ toMap(keyMapper: Stream.Function, mergeFunction?: Stream.Accumulator): Stream.Map;
+ toMap(path: string, mergeFunction?: Stream.Accumulator): Stream.Map;
+}
+
+declare module Stream {
+
+ export interface Map {
+ [index: string]: T
+ }
+
+
+ export interface Sample {
+ [index: string]: any
+ }
+
+ export interface Accumulator {
+ (e1: T, e2: T): T;
+ }
+
+ export interface Collector {
+ supplier: Supplier;
+ accumulator: Stream.Accumulator;
+ finisher: Function;
+ }
+
+ export interface Comparator {
+ (e1: T, e2: T): number
+ }
+
+ export interface Consumer {
+ (elem: T): void;
+ }
+
+ export interface Function {
+ (elem: T): U;
+ }
+
+ export interface GroupingResult {
+ [index: string]: T
+ }
+
+ export interface Iterator {
+ next(): T;
+ done: boolean;
+ }
+
+ export interface JoinOptions {
+ prefix: string;
+ delimiter: string;
+ suffix: string;
+ }
+
+ export interface Predicate {
+ (elem: T): boolean;
+ }
+
+ export interface Supplier {
+ (): T
+ }
+
+ export class Optional {
+ static of(elem: T): Optional;
+ static ofNullable(elem: T): Optional;
+
+ filter(predicate: (elem: T) => boolean): Optional;
+ map(mapper: (elem: T) => U): Optional;
+ flatMap(mapper: (elem: T) => Stream.Optional): Optional;
+ isPresent(): boolean;
+ get(): T;
+ ifPresent(consumer: (elem: T) => void): void;
+ orElse(other: T): T;
+ orElseGet(supplier: Stream.Supplier): T;
+ orElseThrow(error: any): T;
+ }
+}