LINQ to TypeScript
LinqToTypeScript is an active library, currently at stable version 12.1.0, that ports the Language Integrated Query (LINQ) functionality from .NET to TypeScript. It provides a comprehensive set of methods for querying, transforming, and manipulating collections, inspired by the IEnumerable, IAsyncEnumerable, and IParallelEnumerable interfaces. The library supports both synchronous and asynchronous operations, leveraging modern JavaScript features like `AsyncIterable` and `generators`. It targets TypeScript 5.6.X and ES2022, shipping exclusively as ECMAScript Modules (ESM). Key differentiators include its dual usage pattern (explicit `from` wrapper or extending native types via `initializeLinq`), support for parallel operations, and consistent release cadence with new LINQ methods being regularly added.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use CommonJS `require` syntax in a project configured for ECMAScript Modules (ESM) after LinqToTypeScript v11.fixChange `const myLinq = require('linq-to-typescript');` to `import * as myLinq from 'linq-to-typescript';` or `import { from } from 'linq-to-typescript';`. Ensure `"type": "module"` is set in your `package.json`. -
TypeError: (0 , _linqToTypescript.from) is not a function
cause This error typically occurs when there's a module resolution mismatch or incorrect import statement, especially in environments transpiling ESM to CJS, or when `from` is not correctly imported.fixVerify that `import { from } from 'linq-to-typescript';` is used and that your build tools (e.g., Webpack, Rollup, Babel) are configured to correctly handle ESM. Check `tsconfig.json` for `moduleResolution` and `module` settings. -
TS2307: Cannot find module 'linq-to-typescript' or its corresponding type declarations.
cause Incorrect `tsconfig.json` configuration, particularly `target` and `lib` settings not matching the package's requirements, or issues with module resolution.fixEnsure your `tsconfig.json` includes `"target": "es2022"` and `"lib": ["es2022"]`. Also, verify that `moduleResolution` is set appropriately, e.g., `"nodenext"` or `"bundler"` for modern Node.js environments. -
UnhandledPromiseRejectionWarning: TypeError: [some method] is not a function
cause Often happens when attempting to call an asynchronous LINQ method (e.g., `selectAsync`, `asParallel`) without correctly awaiting the `fromAsync` wrapper or the preceding async operation, or if `initializeLinq` for native types isn't called.fixEnsure that `await` is used before calling methods on `IAsyncEnumerable` or `IParallelEnumerable`. If using native extensions, confirm `initializeLinq()` has been called globally before methods are invoked.
Warnings
- breaking Starting with v11.0.0, the package ships exclusively with ECMAScript Modules (ESM). CommonJS is no longer supported, requiring project configuration (e.g., `"type": "module"` in `package.json`) and `import` syntax.
- breaking The `zip` method's behavior was updated in v10.0.0 to align with .NET's implementation when dealing with enumerations of different lengths, which might alter results for existing code relying on previous behavior.
- gotcha LinqToTypeScript v12.0.0 and above are built with TypeScript 5.6.X and target ES2022. While generally backward compatible, using significantly older TypeScript versions in your project might lead to type-checking or build issues.
- gotcha The package requires Node.js version 17 or newer due to its engine specification. Running in older Node.js environments will result in errors.
Install
-
npm install linq-to-typescript -
yarn add linq-to-typescript -
pnpm add linq-to-typescript
Imports
- from
const { from } = require('linq-to-typescript')import { from } from 'linq-to-typescript' - initializeLinq
const { initializeLinq } = require('linq-to-typescript')import { initializeLinq } from 'linq-to-typescript' - IEnumerable
import IEnumerable from 'linq-to-typescript'
import { IEnumerable } from 'linq-to-typescript' - IAsyncEnumerable
import { IAsyncEnumerable } from 'linq-to-typescript'
Quickstart
import { from, 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 String extends IEnumerable<string> { }
}
// 2. Bind Linq Functions to Array, Map, etc
initializeLinq();
async function demonstrateLinq() {
console.log('--- Using Wrapper (from) ---');
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbersWrapper = from(numbers)
.where((x) => x % 2 === 0)
.select((x) => x * 2)
.toArray();
console.log('Even numbers doubled (wrapper):', evenNumbersWrapper); // Expected: [4, 8, 12, 16, 20]
console.log('\n--- Using Extended Native Types ---');
const oddNumbersNative = numbers.where((x) => x % 2 !== 0).toArray();
console.log('Odd numbers (native extension):', oddNumbersNative); // Expected: [1, 3, 5, 7, 9]
console.log('\n--- Async Operations ---');
const asyncData = [10, 20, 30];
const processedAsyncData = await from(asyncData)
.selectAsync(async (x) => {
await new Promise(res => setTimeout(res, 50)); // Simulate async delay
return x + 1;
})
.toArray();
console.log('Processed async data:', processedAsyncData); // Expected: [11, 21, 31]
}
demonstrateLinq();