LINQ for JavaScript
Linq.js is a comprehensive JavaScript implementation of the .NET Language Integrated Query (LINQ) library, offering a fluent API for querying and manipulating data collections. It includes all the original .NET LINQ methods along with several additions, enabling powerful data transformations and filtering across various iterable objects like arrays, Maps, and Sets. The current stable version is 4.0.3, with a release cadence that has provided incremental updates for improved iteration protocol support and enhanced TypeScript definitions. A key differentiator is its transition to a pure ES module structure in version 4.0.0, making it fully compatible with modern JavaScript environments such as Node.js (v14.13.1 and later), TypeScript projects, Deno, and contemporary web browsers. For projects requiring CommonJS modules or targeting older environments, version 3 of the library remains available.
Common errors
-
SyntaxError: Cannot use import statement outside a module
cause Attempting to use ES module `import` syntax for `linq@4+` in a CommonJS Node.js project.fixAdd `'type': 'module'` to your `package.json` or switch to `linq@3` and use `const Enumerable = require('linq')`. -
ReferenceError: Enumerable is not defined
cause Using `require('linq')` with `linq@4+` in a Node.js ES module project, or in an environment where the global `Enumerable` is not exposed (e.g., modern browser without `<script type='module'>`).fixFor `linq@4+`, use `import Enumerable from 'linq'` in an ES module project. For CommonJS, use `linq@3` and `const Enumerable = require('linq')`. -
TypeError: 'Enumerable' is not a constructor
cause The `Enumerable` object is a singleton or a static class-like object, not a constructor. It is meant to be used with static methods like `Enumerable.range()` or `Enumerable.from()`.fixDo not attempt to instantiate `Enumerable` with `new`. Call its static methods directly, e.g., `Enumerable.range(1, 10)` or `Enumerable.from(myArray)`. -
TS2305: Module '"linq"' has no exported member 'IEnumerable'.
cause `IEnumerable` is a type available via the default `Enumerable` import, not a named export itself, or `tsconfig.json` is not configured correctly.fixImport `Enumerable` as a default import and then use `Enumerable.IEnumerable<T>` for type annotation: `import Enumerable from 'linq'; type MyType = Enumerable.IEnumerable<string>;`. Ensure `tsconfig.json` includes `{'compilerOptions': {'target': 'ES2020', 'moduleResolution': 'node'}}`.
Warnings
- breaking Version 4.0.0 fully transitioned to an ES module (ESM) architecture, deprecating CommonJS (CJS) support for the current major release. This means `require()` syntax is no longer supported with `linq@4` and newer.
- gotcha Attempting to use `linq@4` or newer in a Node.js project without configuring it as an ES module will result in module resolution errors. This is typically indicated by a `SyntaxError: Cannot use import statement outside a module`.
- gotcha The library ships with TypeScript definitions, but correct usage requires specific `tsconfig.json` compiler options, particularly `target` set to `ES2020` or higher and `moduleResolution` to `node`.
- gotcha Version 3.2.3 introduced `Enumerable.Utils.recallFrom` which implies that `Enumerable.Utils.extendTo` (for prototype pollution) should be used with extreme caution, as direct prototype extension is generally discouraged in modern JavaScript.
Install
-
npm install linq -
yarn add linq -
pnpm add linq
Imports
- Enumerable
const Enumerable = require('linq')import Enumerable from 'linq'
- IEnumerable<T>
import { IEnumerable } from 'linq'import Enumerable from 'linq'; type MyCollection = Enumerable.IEnumerable<number>;
- Enumerable (CommonJS)
import Enumerable from 'linq'
const Enumerable = require('linq')
Quickstart
// For Node.js (v14.13.1+) with "type": "module" in package.json
import Enumerable from 'linq';
// Example 1: Basic filtering and transformation
let result1 = Enumerable.range(1, 10)
.where(i => i % 3 === 0)
.select(i => i * 10)
.toArray();
console.log('Filtered and multiplied:', result1); // [ 30, 60, 90 ]
// Example 2: Working with objects and iterating over Map/Set
const data = new Map([
['apple', 10],
['banana', 20],
['cherry', 30]
]);
let result2 = Enumerable.from(data)
.where(([key, value]) => value > 15)
.select(([key, value]) => ({ fruit: key, quantity: value * 2 }))
.toArray();
console.log('Querying Map:', result2); // [ { fruit: 'banana', quantity: 40 }, { fruit: 'cherry', quantity: 60 } ]
// Example 3: Finding the first element meeting a condition
let firstBigRadius = Enumerable.toInfinity(1)
.where(r => r * r * Math.PI > 10000)
.first();
console.log('First radius for area > 10000:', firstBigRadius);