arogozine / LinqToTypeScript

LINQ to TypeScript
https://arogozine.github.io/linqtotypescript/
MIT License
140 stars 18 forks source link
async async-await async-iteration enumerable es2019 javascript linq typescript

LINQ To TypeScript

tsconfig.json

"compilerOptions": {
    "target": "es2022",
    "lib": [
      "es2022"
    ]
}

Using the Library

With Wrappers

// 0. Import Module
import { from } from "linq-to-typescript"

// To Use With Wrappers
const evenNumbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9]).where((x) => x % 2 === 0).toArray()

Without Wrappers

// 0. Import Module
import { initializeLinq, IEnumerable } from "linq-to-typescript"
// 1. Declare that the JS types implement the IEnumerable interface
declare global {
    interface Array<T> extends IEnumerable<T> { }
    interface Uint8Array extends IEnumerable<number> { }
    interface Uint8ClampedArray extends IEnumerable<number> { }
    interface Uint16Array extends IEnumerable<number> { }
    interface Uint32Array extends IEnumerable<number> { }
    interface Int8Array extends IEnumerable<number> { }
    interface Int16Array extends IEnumerable<number> { }
    interface Int32Array extends IEnumerable<number> { }
    interface Float32Array extends IEnumerable<number> { }
    interface Float64Array extends IEnumerable<number> { }
    interface Map<K, V> extends IEnumerable<[K, V]> { }
    interface Set<T> extends IEnumerable<T> { }
    interface String extends IEnumerable<string> { }
}
// 2. Bind Linq Functions to Array, Map, etc
initializeLinq()
// 3. Use without a wrapper type
const evenNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9].where((x) => x % 2 === 0).toArray()

Examples

Please refer to the examples folder

ES6 Modules (ESM)

To use library with ES6 modules make sure that you specify "type": "module" in package.json

API

TypeDoc API Surface Documentation

LinqToTypeScript implements the functionality of the IEnumerable interface

IEnumerable

IAsyncEnumerable

IParallelEnumerable

Shared Instance Methods

Method Async* Tests Coverage Notes
aggregate No Sync
all Yes Sync, Async
any Yes Sync, Async
append No Sync
average Yes Sync, Async
chunk No Sync
concatenate No Sync Equivalent to .Concat but renamed to avoid conflict with JS
contains Yes Sync, Async
count Yes Sync, Async
defaultIfEmpty No Sync
distinct Yes Sync, Async
elementAt No Sync
elementAtOrDefault No Sync
except Yes Sync, Async
first Yes Sync, Async
firstOrDefault Yes Sync, Async
each Yes Sync, Async From List<T>.ForEach
groupBy Yes Sync, Async
groupByWithSel No Sync
groupJoin Yes Sync, Async
intersect Yes Sync, Async
joinByKey No Sync
last Yes Sync, Async
lastOrDefault Yes Sync, Async
max Yes Sync, Async
min Yes Sync, Async
ofType No Sync
order No Sync
orderBy Yes Sync, Async
orderByDescending Yes Sync, Async
orderDescending No Sync
partition Yes Sync, Async
prepend No Sync
reverse No Sync
select Yes Sync, Async
selectMany Yes Sync, Async
sequenceEquals Yes Sync, Async
single Yes Sync, Async
singleOrDefault Yes Sync, Async
skip No Sync
skipWhile Yes Sync, Async
sum Yes Sync, Async
take No Sync
takeWhile Yes Sync, Async
toArray No Sync
toMap Yes Sync, Async Equivalent to ToDictionary
toObject Yes Sync, Async
toSet No Sync Equivalent to ToHashSet. No comparer overload for JS.
union Yes Sync
where Yes Sync, Async
zip Yes Sync, Async

* Async methods take an async function

Static Methods

Method Async Parallel Tests Coverage
empty emptyAsync emptyParallel Test
enumerateObject enumerateObjectAsync N/A Test
flatten flattenAsync flattenParallel Test
range rangeAsync rangeParallel Test
repeat repeatAsync repeatParallel Test

Index Methods

Method Notes
bindArray Binds IEnumerable methods to an ArrayLike Iterable type
bindLinq Binds IEnumerable methods to an Interable type
bindLinqAsync Binds IAsyncEnumerable methods to an AsyncIterable type
isEnumerable Determines if source implements IEnumerable
isAsyncEnumerable Determines if source implements IAsyncEnumerable
isParallelEnumerable Determines if source implements IParallelEnumerable
initializeLinq Binds to IEnumerable to Array Types, Map, Set, & String

Exception Types

Exception Notes
ArgumentOutOfRangeException Thrown when a passed in argument is invalid
InvalidOperationException Thrown when no elements or no predicate match

Design

Binding new APIs to Array Types

JavaScript doesn't have extension methods like in C#, therefore we extend the class itself with new methods. Call initializeLinq to bind library functions to default Array methods,

The following collections support IEnumerable,

Using Wrappers

NOTE: Wrappers are safer as they won't interfere with other libraries.

// To Create an IEnumerable<T>
import { from } from "linq-to-typescript"
from(iterableIteratorOrArray)

// To Create an IAsyncEnumerable<T>
import { fromAsync } from "linq-to-typescript"
fromAsync(asyncIterableIteratorOrPromiseArray)

// To Create an IParallelEnumerable<T>
// You have to specify the parallel generator function type
import { fromParallel, ParallelGeneratorType } from "linq-to-typescript"
fromParallel(ParallelGeneratorType.PromiseToArray, asyncFuncThatReturnsAnArray)

Issues and Questions

Q1: How does this compare to other LINQ libraries?

Other libraries tend to use eager evaluation and work with arrays instead of iterables.

Q2: Can I use your code?

With attribution; the code is licensed under MIT.

Q3: Why should I use this instead of lodash or something similar?

The whole library is written in TypeScript first and avoids typechecking done by TypeScript Language Service.

Lazy evaluation. Not much happens until you iterate over the enumerable or conver it to an Array, Map, etc.

Q4: Is IE11 supported?

No.

Q5: Can I contribute?

Please do!