diff --git a/ix.js/ix-tests.ts b/ix.js/ix-tests.ts new file mode 100644 index 000000000..6953621ca --- /dev/null +++ b/ix.js/ix-tests.ts @@ -0,0 +1,116 @@ +/// + +var ec_ns = (a: number, b: string) => a.toString() == b; //equality comparer on number,string +var ec_ss = (a: string, b: string) => a == b; //equality comparer on string,string +var ec_nn = (a: number, b: number) => a === b; //equality comparer on number,number +var c_nn = (a: number, b: number) => a - b; //comparer on number,number + +// static + +Ix.Enumerable.throw(new Error("error")); +Ix.Enumerable.throwException(new Error("error")); + +var ax = Ix.Enumerable.generate(-100, a => a < 100, a=> a + 10, a=> a * 2); + +Ix.Enumerable.defer(() => ax); + +Ix.Enumerable.using(() => ax.getEnumerator(), e => Ix.Enumerable.return(e.getCurrent())); + +Ix.Enumerable.catch(ax, ax, ax); +Ix.Enumerable.catchException(ax, ax, ax); +Ix.Enumerable.catch(); +Ix.Enumerable.catchException(); + +Ix.Enumerable.onErrorResumeNext(ax, ax, ax); +Ix.Enumerable.onErrorResumeNext(); + +Ix.Enumerable.while(x => x.count() > 0, ax); +Ix.Enumerable.whileDo(x => x.count() > 0, ax); + +Ix.Enumerable.if(() => true, ax, ax); +Ix.Enumerable.ifThen(() => true, ax, ax); +Ix.Enumerable.if(() => true, ax); +Ix.Enumerable.ifThen(() => true, ax); + +Ix.Enumerable.doWhile(ax, x => x.count() > 0); + +Ix.Enumerable.case(() => 42, { 42: ax }, ax); +Ix.Enumerable.switchCase(() => 42, { 42: ax }, ax); +Ix.Enumerable.case(() => 42, { 42: ax }); +Ix.Enumerable.switchCase(() => 42, { 42: ax }); +Ix.Enumerable.case(() => "42", { "42": ax }, ax); +Ix.Enumerable.switchCase(() => "42", { "42": ax }, ax); +Ix.Enumerable.case(() => "42", { "42": ax }); +Ix.Enumerable.switchCase(() => "42", { "42": ax }); + +Ix.Enumerable.for(ax, a => ax); +Ix.Enumerable.forIn(ax, a => ax); + +// instance + +var bx: Ix.Enumerable; + +ax.isEmpty(); + +bx.minBy(b => b.length, c_nn); +bx.minBy(b => b.length); +bx.maxBy(b => b.length, c_nn); +bx.maxBy(b => b.length); + +ax.share(ax => bx); +ax.share(); + +ax.publish(ax => bx); +ax.publish(); + +ax.memoize(); + +ax.do({ onNext: (a: number) => console.log(a), onError: err => console.log(err), onCompleted: () => console.log("completed") }); +ax.do(a => console.log(a), err => console.log(err), () => console.log("completed")); +ax.do(a => console.log(a), err => console.log(err)); +ax.do((a: number) => console.log(a)); +ax.doAction({ onNext: (a: number) => console.log(a), onError: err => console.log(err), onCompleted: () => console.log("completed") }); +ax.doAction(a => console.log(a), err => console.log(err), () => console.log("completed")); +ax.doAction(a => console.log(a), err => console.log(err)); +ax.doAction((a: number) => console.log(a)); + +ax.bufferWithCount(10, 20); +ax.bufferWithCount(10); + +ax.ignoreElements(); + +bx.distinctBy(b => b.length, ec_nn); +bx.distinctBy(b => b.length); + +bx.distinctUntilChanged(b => b.length, ec_nn); +bx.distinctUntilChanged(b => b.length); +bx.distinctUntilChanged(); +bx.distinctUntilChanged(false, ec_ss); + +ax.expand(a => ax); + +ax.startWith(10, 20); + +ax.scan(0, (acc, a) => acc + a); +ax.scan((acc, a) => acc + a); + +ax.takeLast(10); +ax.skipLast(10); + +ax.repeat(10); +ax.repeat(); + +ax.catch(ax, ax, ax); +ax.catchException(ax, ax, ax); +ax.catch(ax); +ax.catchException(ax); +ax.catch(err => ax); +ax.catchException(err => ax); + +ax.finally(() => { }); +ax.finallyDo(() => { }); + +ax.onErrorResumeNext(ax); + +ax.retry(10); +ax.retry(); diff --git a/ix.js/ix.d.ts b/ix.js/ix.d.ts new file mode 100644 index 000000000..614a950fb --- /dev/null +++ b/ix.js/ix.d.ts @@ -0,0 +1,112 @@ +// Type definitions for IxJS 1.0.6 / ix.js +// Project: https://github.com/Reactive-Extensions/IxJS +// Definitions by: Igor Oleinikov + +/// + +declare module Ix { + + export interface Observer { + onNext? (value: T): void; + onError? (error: Error): void; + onCompleted? (): void; + } + + export interface Enumerable { + isEmpty(): boolean; + + minBy(keySelector: (item: T) => TKey, comparer: Comparer): Enumerable; + minBy(keySelector: (item: T) => number): Enumerable; + maxBy(keySelector: (item: T) => TKey, comparer: Comparer): Enumerable; + maxBy(keySelector: (item: T) => number): Enumerable; + + share(selector: (source: Enumerable) => Enumerable): Enumerable; + share(): Enumerable; + + publish(selector: (source: Enumerable) => Enumerable): Enumerable; + publish(): Enumerable; + + memoize(): Enumerable; + + do(onNext: (value: T) => void, onError?: (error: Error) => void, onCompleted?: () => void): Enumerable; + doAction(onNext: (value: T) => void, onError?: (error: Error) => void, onCompleted?: () => void): Enumerable; + do(onbserver: Observer): Enumerable; + doAction(onbserver: Observer): Enumerable; + + bufferWithCount(count: number, skip?: number): Enumerable; + + ignoreElements(): Enumerable; + + distinctBy(keySelector: (item: T) => TKey, comparer?: EqualityComparer): Enumerable; + + distinctUntilChanged(keySelector: (item: T) => TKey, comparer?: EqualityComparer): Enumerable; + distinctUntilChanged(): Enumerable; + // if need to set comparer without keySelector + distinctUntilChanged(_: boolean, comparer: EqualityComparer): Enumerable; + + expand(selector: (item: T) => Enumerable): Enumerable; + + startWith(...values: T[]): Enumerable; + + scan(seed: TSeed, accumulate: (acc: TAccumulator, item: T) => TAccumulator): Enumerable; + scan(accumulate: (acc: T, item: T) => T): Enumerable; + + takeLast(count: number): Enumerable; + skipLast(count: number): Enumerable; + + repeat(count?: number): Enumerable; + + catch(handler: (error: Error) => Enumerable): Enumerable; + catchException(handler: (error: Error) => Enumerable): Enumerable; + catch(second: Enumerable, ...other: Enumerable[]): Enumerable; + catchException(second: Enumerable, ...other: Enumerable[]): Enumerable; + + // todo: Enumerable>.catch(): Enumerable + //catch>(): Enumerable; + + finally(finallyAction: () => void): Enumerable; + finallyDo(finallyAction: () => void): Enumerable; + + onErrorResumeNext(second: Enumerable): Enumerable; + + retry(retryCount?: number): Enumerable; + } + + export interface EnumerableStatic { + throw(error: Error): Enumerable; + throwException(error: Error): Enumerable; + + defer(enumerableFactory: () => Enumerable): Enumerable; + + generate( + initialState: TState, + condition: Predicate, + iterate: (state: TState) => TState, + resultSelector: (state: TState) => TResult): Enumerable; + + using( + resourceFactory: () => TResource, + enumerableFactory: (resource: TResource) => Enumerable): Enumerable; + + catch(...sources: Enumerable[]): Enumerable; + catchException(...sources: Enumerable[]): Enumerable; + + onErrorResumeNext(...sources: Enumerable[]): Enumerable; + + while(condition: EnumerablePredicate>, source: Enumerable): Enumerable; + whileDo(condition: EnumerablePredicate>, source: Enumerable): Enumerable; + + if(condition: () => boolean, thenSource: Enumerable, elseSource?: Enumerable): Enumerable; + ifThen(condition: () => boolean, thenSource: Enumerable, elseSource?: Enumerable): Enumerable; + + doWhile(source: Enumerable, condition: EnumerablePredicate>): Enumerable; + + case(selector: () => number, sources: { [key: number]: Enumerable; }, defaultSource?: Enumerable): Enumerable; + case(selector: () => string, sources: { [key: string]: Enumerable; }, defaultSource?: Enumerable): Enumerable; + switchCase(selector: () => number, sources: { [key: number]: Enumerable; }, defaultSource?: Enumerable): Enumerable; + switchCase(selector: () => string, sources: { [key: string]: Enumerable; }, defaultSource?: Enumerable): Enumerable; + + for(source: Enumerable, resultSelector: EnumerableFunc): Enumerable; + forIn(source: Enumerable, resultSelector: EnumerableFunc): Enumerable; + } +} diff --git a/ix.js/l2o-tests.ts b/ix.js/l2o-tests.ts new file mode 100644 index 000000000..2399d4e9f --- /dev/null +++ b/ix.js/l2o-tests.ts @@ -0,0 +1,221 @@ +/// + +var ec_ns = (a: number, b: string) => a.toString() == b; //equality comparer on number,string +var ec_nn = (a: number, b: number) => a === b; //equality comparer on number,number +var c_nn = (a: number, b: number) => a - b; //comparer on number,number + +// static + +var ax = Ix.Enumerable.fromArray([0, 2, 7, 3, 4, 5]); + +var bx = Ix.Enumerable.create(() => { + var current = "."; + return Ix.Enumerator.create( + () => { current += "."; return true; }, + () => current, + () => { }); +}); + +Ix.Enumerator.create(() => true, () => 1); // without dispose method + +var cx = Ix.Enumerable.empty(); + +var dx = Ix.Enumerable.concat(ax, cx); + +var ex = Ix.Enumerable.return(42); +var fx = Ix.Enumerable.returnValue("42"); + +var gx = Ix.Enumerable.range(-100, 200); + +Ix.Enumerable.repeat(42, 42); +Ix.Enumerable.repeat(42); // infinite + +Ix.Enumerable.sequenceEqual(ax, fx, ec_ns); +Ix.Enumerable.sequenceEqual(ax, ex); // default comparer on same type + +// instance + +ax.getEnumerator(); + +ax.aggregate("", (acc, i) => acc + i, acc=> acc.length); +ax.aggregate("", (acc, i) => acc + i); +ax.aggregate((acc, i) => acc + i); + +ax.reduce((acc, i) => acc + i, 100); +ax.reduce((acc, i) => acc + i); + +ax.all(item => true); +ax.all(item => true, bx); +ax.every(item => true); +ax.every(item => true, bx); + +ax.any(); +ax.any(item => true); +ax.any(item => true, bx); +ax.some(); +ax.some(item => true); +ax.some(item => true, bx); + +ax.average(); +bx.average(item => item.length); +ax.min(); +bx.min(item => item.length); +ax.max(); +bx.max(item => item.length); +ax.sum(); +bx.sum(item => item.length); + +ax.concat(ax, cx, dx, ex, gx); + +ax.contains(10); +ax.contains("10", ec_ns); + +ax.count(); +ax.count(item=>false); +ax.count(item=> false, {}); + +cx.defaultIfEmpty(); +cx.defaultIfEmpty(10); + +dx.distinct(); +dx.distinct((d1, d2) => d1 === d2); + +ax.elementAt(2); +ax.elementAtOrDefault(2); + +//ax.except(bx, ec_ns); // bug https://typescript.codeplex.com/workitem/1841 +bx.except(fx); + +ax.first(); +ax.firstOrDefault(); +ax.last(); +ax.lastOrDefault(); +ax.single(); +ax.singleOrDefault(); + +ax.forEach(a => console.log(a)); +ax.forEach(a => console.log(a), cx); + +//bx.groupBy(b => b.length); // spec 3.5.2, waiting for restriction on generative recursion removal +bx.groupBy(b => b.length, b => "[" + b + "]"); +bx.groupBy(b => b.length, b => "[" + b + "]", (l, values) => l + values.count()); +bx.groupBy(b => b.length, false, (l, values) => l + values.count()); +bx.groupBy(b => b.length, b => "[" + b + "]", (l, values) => l + values.count(), ec_nn); +bx.groupBy(b => b.length, b => "[" + b + "]", false, (x, y) => x == y); +bx.groupBy(b => b.length, false, (l, values) => l + values.count(), ec_nn); +//bx.groupBy(b => b.length, false, false, ec_nn); // spec 3.5.2, waiting for restriction on generative recursion removal + +ax.groupJoin(bx, a => a, b => b, (a, b) => [a, b], ec_ns); +ax.groupJoin(bx, a => a, b => b.length, (a, b) => [a, b]); + +ax.join(bx, a => a, b => b, (a, b) => [a, b], ec_ns); +ax.join(bx, a => a, b => b.length, (a, b) => [a, b]); + +//ax.intersect(bx, ec_ns); // bug https://typescript.codeplex.com/workitem/1841 +ax.intersect(cx); +ax.union(cx); + +ax.orderBy(a=> -a).thenBy(a => a); +ax.orderBy(a=> -a, c_nn).thenBy(a => a, c_nn); +ax.orderByDescending(a=> -a).thenByDescending(a => a); +ax.orderByDescending(a=> -a, c_nn).thenByDescending(a => a, c_nn); + +ax.reverse(); + +ax.select(a=> a.toString()); +ax.select(a=> a.toString(), {}); +ax.map(a=> a.toString()); +ax.map(a=> a.toString(), {}); + +ax.selectMany(a=> bx); +ax.selectMany(a=> bx, (a, b) => [a, b]); + +ax.sequenceEqual(fx, ec_ns); +ax.sequenceEqual(ax, ec_nn); +ax.sequenceEqual(cx); + +ax.skip(10); +ax.skipWhile(a => a > 10); +ax.take(10); +ax.takeWhile(a => a > 10); + +ax.toArray(); + +bx.toDictionary(b => b.length, b => 10, ec_nn); +//bx.toDictionary(b => b.length, false, ec_nn); // spec 3.5.2, waiting for restriction on generative recursion removal +bx.toDictionary(b => b.length, b => 10); +//bx.toDictionary(b => b.length); // spec 3.5.2, waiting for restriction on generative recursion removal + +bx.toLookup(b => b.length, b => 10, ec_nn); +//bx.toLookup(b => b.length, false, ec_nn); // spec 3.5.2, waiting for restriction on generative recursion removal +bx.toLookup(b => b.length, b => 10); +//bx.toLookup(b => b.length); // spec 3.5.2, waiting for restriction on generative recursion removal + +ax.where(a=> a > 10, {}); +ax.where(a=> a > 10); +ax.filter(a=> a > 10, {}); +ax.filter(a=> a > 10); + +ax.zip(bx, (a: number, b: string) => [a, b]); +ax.zip(bx, (a, b) => [a, b]); + +// Disposable + +{ + var d: Ix.Disposable; + + d.dispose(); +} + +// Enumerator + +{ + var e: Ix.Enumerator; + + try { + while (e.moveNext()) { var c = e.getCurrent(); } + } + finally { + e.dispose(); + } +} + +// Dictionary + +{ + var dic = new Ix.Dictionary(0, ec_nn); + + var key = dic.toEnumerable().first().key; + var value = dic.toEnumerable().first().value; + + dic.add(1, "1"); + dic.remove(1); + dic.clear(); + dic.length(); + dic.tryGetValue(1); + dic.get(1); + dic.set(1, "1"); + dic.getValues(); + dic.has(1); +} + +// KeyValuePair + +{ + var kv: Ix.KeyValuePair; + var key = kv.key; + var value = kv.value; +} + +// Lookup + +{ + var lookup: Ix.Lookup; + + var key = lookup.toEnumerable().first().key; + lookup.toEnumerable().first().first(); + + lookup.has(1); + lookup.length(); + lookup.get(1).first(); +} \ No newline at end of file diff --git a/ix.js/l2o.d.ts b/ix.js/l2o.d.ts new file mode 100644 index 000000000..c3f3c415e --- /dev/null +++ b/ix.js/l2o.d.ts @@ -0,0 +1,256 @@ +// Type definitions for IxJS 1.0.6 / l2o.js +// Project: https://github.com/Reactive-Extensions/IxJS +// Definitions by: Igor Oleinikov + +declare module Ix { + export interface Disposable { + dispose(): void; + } + + export interface Enumerator extends Disposable { + moveNext(): boolean; + getCurrent(): T; + } + + export interface EnumeratorStatic { + new (moveNext: () => boolean, getCurrent: () => T, dispose: () => void): Enumerator; + create(moveNext: () => boolean, getCurrent: () => T, dispose?: () => void): Enumerator; + } + + var Enumerator: EnumeratorStatic; + + export interface EnumerableFunc { + (item: T, index: number, self: Enumerable): TResult; + } + export interface EnumerablePredicate extends EnumerableFunc { } + export interface Predicate { + (item: T): boolean; + } + export interface EqualityComparer { + (item1: TFirst, item2: TSecond): boolean; + } + export interface Comparer { + (item1: TFirst, item2: TSecond): number; + } + + export interface Enumerable { + // base functions + getEnumerator(): Enumerator; + + // "extension" functions + + aggregate(seed: TAccumulate, func: (accumulate: TAccumulate, current: T, index: number, self: Enumerable) => TAccumulate, resultSelector: (accumulate: TAccumulate) => TResult): TResult; + aggregate(seed: TAccumulate, func: (accumulate: TAccumulate, current: T, index: number, self: Enumerable) => TAccumulate): TAccumulate; + aggregate(func: (accumulate: T, current: T, index: number, self: Enumerable) => T): T; + + reduce(func: (accumulate: T, current: T, index: number, self: Enumerable) => T): T; + reduce(func: (accumulate: TAccumulate, current: T, index: number, self: Enumerable) => TAccumulate, seed: TAccumulate): TAccumulate; + + all(predicate: EnumerablePredicate, thisArg?: any): boolean; + every(predicate: EnumerablePredicate, thisArg?: any): boolean; // alias + + any(predicate?: EnumerablePredicate, thisArg?: any): boolean; + some(predicate?: EnumerablePredicate, thisArg?: any): boolean; // alias + + average(selector?: EnumerableFunc): number; + max(selector?: EnumerableFunc): number; + min(selector?: EnumerableFunc): number; + sum(selector?: EnumerableFunc): number; + + concat(...sources: Enumerable[]): Enumerable; + + contains(value: TValue, comparer: EqualityComparer): boolean; + contains(value: T): boolean; + + count(predicate?: EnumerablePredicate, thisArg?: any): number; + + defaultIfEmpty(defaultValue?: T): Enumerable; + + distinct(comparer?: EqualityComparer): Enumerable; + + elementAt(index: number): T; + elementAtOrDefault(index: number): T; + + except(second: Enumerable, comparer: EqualityComparer): Enumerable; + except(second: Enumerable): Enumerable; + + first(predicate?: Predicate): T; + firstOrDefault(predicate?: Predicate): T; + last(predicate?: Predicate): T; + lastOrDefault(predicate?: Predicate): T; + single(predicate?: Predicate): T; + singleOrDefault(predicate?: Predicate): T; + + forEach(action: EnumerableFunc, thisArg?: any): void; + + groupBy( + keySelector: (item: T) => TKey, + elementSelector: (item: T) => TElement, + resultSelector: (key: TKey, values: Enumerable) => TResult, + comparer?: EqualityComparer): Enumerable; + groupBy( + keySelector: (item: T) => TKey, + elementSelector: (item: T) => TElement): Grouping; + // spec 3.5.2, waiting for restriction on generative recursion removal + /*groupBy( + keySelector: (item: T) => TKey): Grouping;*/ + + // if need to set comparer without resultSelector + groupBy( + keySelector: (item: T) => TKey, + elementSelector: (item: T) => TElement, + _: boolean, + comparer: EqualityComparer): Grouping; + // if need to set resultSelector without elementSelector + groupBy( + keySelector: (item: T) => TKey, + _: boolean, + resultSelector: (key: TKey, values: Enumerable) => TResult, + comparer?: EqualityComparer): Enumerable; + // if need to set comparer without elementSelector and resultSelector + // spec 3.5.2, waiting for restriction on generative recursion removal + /*groupBy( + keySelector: (item: T) => TKey, + _: boolean, + __: boolean, + comparer: EqualityComparer): Grouping;*/ + + groupJoin( + inner: Enumerable, + outerKeySelector: (item: T) => TOuterKey, + innerKeySelector: (item: TInner) => TInnerKey, + resultSelector: (outer: T, innerSequence: Enumerable) => TResult, + comparer: EqualityComparer): Enumerable; + groupJoin( + inner: Enumerable, + outerKeySelector: (item: T) => TKey, + innerKeySelector: (item: TInner) => TKey, + resultSelector: (outer: T, innerSequence: Enumerable) => TResult): Enumerable; + + join( + inner: Enumerable, + outerKeySelector: (item: T) => TOuterKey, + innerKeySelector: (item: TInner) => TInnerKey, + resultSelector: (outer: T, inner: TInner) => TResult, + comparer: EqualityComparer): Enumerable; + join( + inner: Enumerable, + outerKeySelector: (item: T) => TKey, + innerKeySelector: (item: TInner) => TKey, + resultSelector: (outer: T, inner: TInner) => TResult): Enumerable; + + intersect(second: Enumerable, comparer: EqualityComparer): Enumerable; + intersect(second: Enumerable): Enumerable; + union(second: Enumerable, comparer?: EqualityComparer): Enumerable; + + orderBy(keySelector: (item: T) => TKey, comparer?: Comparer): OrderedEnumerable; + orderByDescending(keySelector: (item: T) => TKey, comparer?: Comparer): OrderedEnumerable; + + reverse(): Enumerable; + + select(selector: EnumerableFunc, thisArg?: any): Enumerable; + map(selector: EnumerableFunc, thisArg?: any): Enumerable; + + selectMany(collectionSelector: (item: T, index: number) => Enumerable, + resultSelector: (outer: T, inner: TCollection) => TResult): Enumerable; + selectMany(collectionSelector: (item: T, index: number) => Enumerable): Enumerable; + + sequenceEqual(second: Enumerable, comparer: EqualityComparer): boolean; + sequenceEqual(second: Enumerable): boolean; + + skip(count: number): Enumerable; + skipWhile(selector: EnumerablePredicate, thisArg?: any): Enumerable; + take(count: number): Enumerable; + takeWhile(selector: EnumerablePredicate, thisArg?: any): Enumerable; + + toArray(): T[]; + + toDictionary( + keySelector: (item: T) => TKey, + elementSelector: (item: T) => TValue, + comparer?: EqualityComparer): Dictionary; + // spec 3.5.2, waiting for restriction on generative recursion removal + /*toDictionary( + keySelector: (item: T) => TKey): Dictionary;*/ + // if need to set comparer without elementSelector + // spec 3.5.2, waiting for restriction on generative recursion removal + /*toDictionary( + keySelector: (item: T) => TKey, + _: boolean, + comparer: EqualityComparer): Dictionary;*/ + + toLookup( + keySelector: (item: T) => TKey, + elementSelector: (item: T) => TValue, + comparer?: EqualityComparer): Lookup; + // spec 3.5.2, waiting for restriction on generative recursion removal + /*toLookup( + keySelector: (item: T) => TKey): Lookup;*/ + // if need to set comparer without elementSelector + // spec 3.5.2, waiting for restriction on generative recursion removal + /*toLookup( + keySelector: (item: T) => TKey, + _: boolean, + comparer: EqualityComparer): Lookup;*/ + + where(selector: EnumerablePredicate, thisArg?: any): Enumerable; + filter(selector: EnumerablePredicate, thisArg?: any): Enumerable; + + zip(right: Enumerable, selector: (left: T, right: TRight) => TResult): Enumerable; + } + + export interface Grouping extends Enumerable { + key: TKey; + } + + export interface OrderedEnumerable extends Enumerable { + thenBy(keySelector: (item: T) => TKey, comparer?: Comparer): OrderedEnumerable; + thenByDescending(keySelector: (item: T) => TKey, comparer?: Comparer): OrderedEnumerable; + } + + class Dictionary { + constructor(capacity?: number, comparer?: EqualityComparer); + + toEnumerable(): Enumerable>; + + add(key: TKey, value: TValue): void; + remove(key: TKey): boolean; + clear(): void; + length(): number; + tryGetValue(key: TKey): TValue; + get(key: TKey): TValue; + set(key: TKey, value: TValue): void; + getValues(): TValue[]; + has(key: TKey): boolean; + } + + export interface KeyValuePair { + key: TKey; + value: TValue; + } + + export interface Lookup { + toEnumerable(): Enumerable>; + has(key: TKey): boolean; + length(): number; + get(key: TKey): Enumerable; + } + + export interface EnumerableStatic { + new (getEnumerator: () => Enumerator): Enumerable; + create(getEnumerator: () => Enumerator): Enumerable; + + concat(...sources: Enumerable[]): Enumerable; + empty(): Enumerable; + fromArray(array: T[]): Enumerable; + return(value: T): Enumerable; + returnValue(value: T): Enumerable; // alias for ; + repeat(value: T, repeatCount?: number): Enumerable; + + sequenceEqual(first: Enumerable, second: Enumerable, comparer: EqualityComparer): boolean; + sequenceEqual(first: Enumerable, second: Enumerable): boolean; + } + + var Enumerable: EnumerableStatic; +} \ No newline at end of file