Giter Site home page Giter Site logo

mkloubert / node-enumerable Goto Github PK

View Code? Open in Web Editor NEW
14.0 3.0 4.0 705 KB

ES2017 ready LINQ features written in TypeScript.

License: MIT License

TypeScript 98.62% JavaScript 1.38%
es6-javascript javascript ecmascript ecmascript2015 linq linq-methods arrays iterator generators nodejs-library

node-enumerable's Introduction

npm npm

node-enumerable

ES2017 ready LINQ library written in TypeScript.

Donate

Table of contents

  1. Requirements
  2. Installation
  3. Usage
  4. Playground / demos
  5. Examples
  6. Documentation
  7. License
  8. Tests

Requirements []

Installation []

NodeJS []

Run

npm install node-enumerable --save

inside project folder to install the module.

The module requires at least Node.js 12+.

Browser []

Download the latest version from here.

<html>
  <head>
    <!-- node-enumerable -->
    <script type="text/javascript" src="js/enumerable.js"></script>
  </head>

  <body>
    <script type="text/javascript">
    
        // test code

        let seq = Enumerable.create(1, 2, 3);

        for (let item of seq) {
            alert(item);
        }
    
    </script>
  </body>
</html>

Usage []

Create a sequence []

const Enumerable = require('node-enumerable');

function *testGenerator() {
    yield 111;
    yield 222;
    yield 333;
}

// from a list of values / objects with variable length
let seq1 = Enumerable.create(1, 'MK', true, null, {});

// from an array
let seq2 = Enumerable.from([11, 22, 33, 44]);
// from a generator
let seq3 = Enumerable.from( testGenerator() );
// from a string
// 
// 'A', 'j', 'n', 'a', 't'
let seq4 = Enumerable.from('Ajnat');  // alt: Enumerable.fromString('Ajnat');

// range of numbers: 2, 3, 4, 5, 6
let seq5 = Enumerable.range(2, 5);

// 5979 'TM' strings
let seq6 = Enumerable.repeat('TM', 5979);

// build, using factory function
// 
// 'item_1', 'item_2', 'item_3'
let seq7 = Enumerable.build((cancel, index) => {
    if (index < 3) {
        return 'item_' + (index + 1);
    }
    else {
        cancel();  // we tell that we
                   // want to cancel here
    }
});

// build, using factory function
// by building a flatten list
// 
// 1, 10, 100, 2, 20, 200, 3, 30, 300
let seq8 = Enumerable.buildMany((cancel, index) => {
    let n = index + 1;

    return [ n, n * 10, n * 100 ];
}, 3);  // create 3 elements
        // 
        // the 'build()' function has
        // a same argument

// create empty sequence
let seq9 = Enumerable.empty();

Work with them []

let seq = Enumerable.create(5979, 23979, null, '23979', 1781, 241279);

let newSeq = seq.where((x) => x !== null)  // remove all elements that are (null)
                .skip(1)  // skip one element (5979)
                .take(3)  // take next remaining 3 elements (23979, 23979, 1781)
                .distinct()  // remove duplicates
                .select((x) => "" + x)  // convert to strings
                .order();  // order by element ascending

// you also can use the
// 'each' and 'forEach' methods
// of the sequence to do the
// following job
for (let item of newSeq) {
    // [0] 1781
    // [1] 23979
    console.log(item);
}

Most methods are chainable as in .NET context.

Async operations []

const FS = require('fs');
const Path = require('path');

let seq = Enumerable.create('file1.txt', 'file2.txt', 'file3.txt', 'file4.txt');

seq.async((context) => {
    if (context.isFirst) {
        context.result = 0;  // initialize a counter
                             // value for the result
                             // s. 'counter' parameter
                             // of then() method below
    }

    // [0] file1.txt
    // [1] file2.txt
    // [2] file3.txt
    // [3] file4.txt
    let fileName = context.item;

    let fullPath = Path.join(__dirname, fileName);

    if (context.index < 2) {
        FS.readFile(fullPath, (err, data) => {
            if (err) {
                context.reject(err);  // has to be called if action
                                      // FAILED with the error object
                                      // or value as argument
            }
            else {
                ++context.result;  // update counter value
                                   // for the result
                                   // s. 'counter' of then()
                                   // method below

                context.resolve();  // has to be invoked if
                                    // invocation was SUCCESSFUL
            }
        });
    }
    else {
        context.cancel();  // cancel at 3rd element
    }
}).then((counter) => {
    // OK

    console.log('Number of loaded files: ' + counter);  // 2
}).catch((err) => {
    console.log('One action failed: ' + err);
});

The context argument of the async() method uses the AsyncActionContext interface.

Playground / demos []

You can test all features in your browser.

Examples []

Filters []

// distinct()
// 1, 2, 4, 3
Enumerable.create(1, 2, 4, 2, 3)
          .distinct();
// distinctBy()
// "grape", "passionfruit", "banana", "raspberry"
Enumerable.create("grape", "passionfruit", "banana", "mango", 
                  "orange", "raspberry", "apple", "blueberry")
          .distinctBy(x => x.length);
 
// except()
// 2.0, 2.1, 2.3, 2.4, 2.5
Enumerable.create(2.0, 2.1, 2.2, 2.3, 2.4, 2.5)
          .except([2.2]); 
 
// intersect()
// 26, 30
Enumerable.create(44, 26, 92, 30, 71, 38)
          .intersect([30, 59, 83, 47, 26, 4, 3]);
       
// ofType()
// '5979', 'Tanja'
Enumerable.create(1, '5979', 2, 'Tanja', 3)
          .ofType('string');  // typeof x === 'string'
          
// union()
// 5, 3, 9, 7, 8, 6, 4, 1, 0
Enumerable.create(5, 3, 9, 7, 5, 9, 3, 7)
          .union([8, 3, 6, 4, 4, 9, 1, 0]);
          
// where()
// 1, 2, 3
Enumerable.create(1, 2, 3, 4)
          .where((x) => x < 4);

Sort elements []

// orderBy(), thenBy()
//
// "apple", "grape", "mango", "banana",
// "orange", "blueberry", "raspberry", "passionfruit"
Enumerable.create("grape", "passionfruit", "banana", "mango", 
                  "orange", "raspberry", "apple", "blueberry")
          .orderBy((x) => x.length)  // complement: orderByDescending()
          .thenBy((x) => x);  // complement: thenByDescending()
                              // shorter: then()

// reverse()
// 4, 3, 2, 1
Enumerable.create(1, 2, 3, 4)
          .reverse();

// rand()
// e.g.: 2, 5, 7, 8, 0, 4, 6, 9, 3, 1
Enumerable.range(0, 10)
          .rand();  // alt: shuffle()

Take / skip elements []

// skip()
// 3, 4
Enumerable.create(0, 1, 2, 3, 4)
          .skip(3);

// skipLast()
// 0, 1, 2, 3
Enumerable.create(0, 1, 2, 3, 4)
          .skipLast();

// skipWhile()
// 55, 666, 77
Enumerable.create(22, 33, 44, 55, 666, 77)
          .skipWhile((x) => x < 50);
          
// take()
// 0, 1, 2
Enumerable.create(0, 1, 2, 3, 4)
          .take(3);

// takeWhile()
// 22, 33, 44
Enumerable.create(22, 33, 44, 55)
          .takeWhile((x) => x < 50);

Get one element []

// elementAt()
// 33
Enumerable.create(11, 22, 33, 44)
          .elementAt(2);
          
// elementAtOrDefault()
// 'TM'
Enumerable.create(11, 22, 33, 44)
          .elementAtOrDefault(4, 'TM');  // out of range
          
// first()
// 11
Enumerable.create(11, 22, 33, 44)
          .first();
          
// firstOrDefault()
// 'MK'
Enumerable.create()
          .firstOrDefault('MK');
          
// last()
// 44
Enumerable.create(11, 22, 33, 44)
          .last();
          
// lastOrDefault()
// 'PZ'
Enumerable.create()
          .lastOrDefault('PZ');

// single()
// EXCEPTION, because we have more than one element
Enumerable.create(11, 22, 33, 44)
          .single();
          
// singleOrDefault()
// 11
Enumerable.create(11)
          .singleOrDefault('YS');

All methods with NO OrDefault suffix will throw exceptions if no element was found.

You also can use a function as first argument for all of these methods that works as filter / condition:

// first()
// 22
Enumerable.create(11, 22, 33, 44)
          .first((x) => x >= 20);

Accumulators []

// aggregate()
// " Marcel Joachim Kloubert"
Enumerable.create('Marcel', 'Joachim', 'Kloubert')
          .aggregate((accumulator, item) => {
                         return accumulator += ' ' + item;
                     }, '');

// average()
// 2.5
Enumerable.create(1, 2, 3, 4)
          .average();

// "M., Tanja"
Enumerable.create('M.', 'Tanja')
          .joinToString(', ');

Minimum / maximum values []

// max()
// 3
Enumerable.create(1, 3, 2)
          .max(); 
          
// min()
// 1
Enumerable.create(2, 3, 1, 2)
          .min();

Joins []

class Person {
    constructor(name: string) {
        this.name = name;
    }

    public name: string;
}

class Pet {
    constructor(name: string, owner: Person) {
        this.name = name;
        this.owner = owner;
    }

    public name: string;
    public owner: Person;
}

let persons = [
    new Person("Tanja"),
    new Person("Marcel"),
    new Person("Yvonne"),
    new Person("Josefine")
];

let pets = [
    new Pet("Gina", persons[1]),
    new Pet("Schnuffi", persons[1]),
    new Pet("Schnuffel", persons[2]),
    new Pet("WauWau", persons[0]),
    new Pet("Lulu", persons[3]),
    new Pet("Asta", persons[1]),
];

// groupJoin()
// 
// [0] 'Owner: Tanja; Pets: WauWau, Sparky'
// [1] 'Owner: Marcel; Pets: Gina, Schnuffi, Asta'
// [2] 'Owner: Yvonne; Pets: Schnuffel'
// [3] 'Owner: Josefine; Pets: Lulu'
Enumerable.from(persons)
          .groupJoin(pets,
                     (person) => person.name,
                     (pet) => pet.owner.name,
                     (person, petsOfPerson) => {
                         let petList = petsOfPerson
                             .select(pet => pet.name)
                             .joinToString(', ');
                     
                         return 'Owner: ' + person.name + '; Pets: ' + petList;
                     });

// join()
// 
// [0] 'Owner: Tanja; Pet: WauWau'
// [1] 'Owner: Marcel; Pet: Gina'
// [2] 'Owner: Marcel; Pet: Schnuffi'
// [3] 'Owner: Marcel; Pet: Asta'
// [4] 'Owner: Yvonne; Pet: Schnuffel'
// [5] 'Owner: Josefine; Pet: Lulu'
Enumerable.from(persons)
          .join(pets,
                (person) => person.name,
                (pet) => pet.owner.name,
                (person, pet) => {
                    return 'Owner: ' + person.name + '; Pet: ' + pet.name;
                });

Groupings []

// groupBy()
Enumerable.create("grape", "passionfruit", "blueberry",
                  "apple", "banana")
          .groupBy(fruit => fruit[0].toLowerCase())
          .each((grouping) => {
                    // grouping[0].key = 'g'
                    // grouping[0][0] = 'grape'
                    
                    // grouping[1].key = 'p'
                    // grouping[1][0] = 'passionfruit'
                    
                    // grouping[2].key = 'b'
                    // grouping[2][0] = 'blueberry'
                    // grouping[2][1] = 'banana'
                    
                    // grouping[3].key = 'a'
                    // grouping[3][0] = 'apple'
                });

Projection []

// flatten()
// 1, (false), 3, 44, '555', 66.6, (true)
Enumerable.from( [ [ 1, false, 3 ], 44, [ '555', 66.6, true ] ] )
          .flatten();

// select()
// "MARCEL", "KLOUBERT"
Enumerable.create("Marcel", "Kloubert")
          .select(x => x.toUpperCase());
          
// selectMany()
// 1, 10, 100, 2, 20, 200, 3, 30, 300
Enumerable.create(1, 2, 3)
          .selectMany(x => [ x, x * 10, x * 100 ]);

// zip()
// "Marcel Kloubert", "Bill Gates", "Albert Einstein"
Enumerable.create('Marcel', 'Bill', 'Albert')
          .zip(['Kloubert', 'Gates', 'Einstein', 'Adenauer'],
               (firstName, lastName) => {
                   return `${firstName} ${lastName}`;
               });

Checks / conditions []

// all()
// (false)
Enumerable.create(1, 2, '3', 4)
          .all((x) => typeof x !== "string");

// any()
// (true)
Enumerable.create(1, 2, '3', 4)
          .any((x) => typeof x === "string");

// contains()
// (true)
Enumerable.create(1, 2, '3')
          .contains(3);

// not()
// 1, 2, 4
Enumerable.create(1, 2, '3', 4)
          .not((x) => typeof x === "string");
 
// sequenceEqual()
// (false)         
Enumerable.create(1, 2, 3)
          .sequenceEqual([1, 3, 2]);

Conversions []

// toArray()
let jsArray = Enumerable.create(1, 2, 3, 4)
                        .toArray();
  
// toObject()
let obj = Enumerable.create(1, 2, 3, 4)
                    .toObject((item, index) => "item" + index);  

// toLookup()
// 
// lookup['A'][0] = 'Albert'
// lookup['B'][0] = 'Bill'
// lookup['B'][1] = 'barney'
// lookup['K'][0] = 'Konrad'
// lookup['M'][0] = 'Marcel'
let lookup = Enumerable.create('Bill', 'Marcel', 'barney', 'Albert', 'Konrad')
                       .toLookup(x => x[0].toUpperCase());

Count []

// 3
Enumerable.create(0, 1, 2)
          .count();  // a second call will return 0
                     // if reset() method is not called
          
// 2
Enumerable.create(0, 1, 2)
          .count((x) => x > 0);

// 4
Enumerable.create(11, 22, 33, 44)
          .length();  // a second call will return
                      // the same value, because we have an array
                      // based sequence here
                      //
                      // a generator based sequence will behave as count()

// (false)
Enumerable.create(111, 222, 333)
          .isEmpty();

// all are (false)
Enumerable.isNullOrEmpty(
    Enumerable.create(1111, 2222, 3333)
);
Enumerable.isUndefinedNullOrEmpty(
    Enumerable.create(11111, 22222, 33333)
);
Enumerable.isUndefinedNullOrEmpty(
    Enumerable.create(0, true, false)
);

Math []

// abs()
// 1, 22.57, 444, NaN, -333.85, NaN
Enumerable.create(-1, 22.57, 444, true, -333.85, false)
          .abs();

// ceil()
// -1, 23, 444, NaN, -333, NaN
Enumerable.create(-1, 22.47, 444, null, -333.85, false)
          .ceil();

// cos()
// 0.004, -0.99996, -0.01
Enumerable.create(11, 22, 33)
          .cos();  // complement: arcCos()

// cosH()
// 29937.07, 1792456423.07, 107321789892958.03
Enumerable.create(11, 22, 33)
          .cosH();  // complement: arcCosH()

// exp()
// 2.72, 7.39, 20.09
Enumerable.create(1, 2, 3)
          .exp();

// floor()
// -1, 23, 444, NaN, -334, NaN
Enumerable.create(-1, 22.47, 444.0, undefined, -333.85, true)
          .floor();

// log()
// 0, 1, 2, 3, 4
Enumerable.create(1, 2, 4, 8, 16)
          .log(2);

// pow()
// 1, 4, 9, 16
Enumerable.create(1, 2, 3, 4)
          .pow(2);

// product()
// 24
Enumerable.create(1, 2, 3, 4)
          .product();

// root()
// 1, 2, 3, 4
Enumerable.create(1, 8, 27, 64)
          .root(3);

// round()
// -1, 23, 444, NaN, -334, 2, NaN
Enumerable.create(-1, 22.47, 444.0, undefined, -333.85, 1.5, true)
          .round();

// sin()
// 0.84, 0.91, 0.14
Enumerable.create(1, 2, 3)
          .sin();  // complement: arcSin()

// sinH()
// 1.18, 3.63, 10.02
Enumerable.create(1, 2, 3)
          .sinH();  // complement: arcSinH()

// sqrt()
// 1, 2, 3, 4
Enumerable.create(1, 4, 9, 16)
          .sqrt();

// sum()
// 10
Enumerable.create(1, 2, 3, 4)
          .sum();

// tan()
// 1.72, -1.76, -0.01
Enumerable.create(111, 222, 333)
          .tan();  // complement: arcTan()

// tanH()
// 0, 0.46, -0.76
Enumerable.create(0, 0.5, -1)
          .tanH();  // complement: arcTanH()

More []

assert []

let seq1 = Enumerable.range(0, 10);
seq1.assert((x) => {
    return x % 2 !== 1;
});  // will throw an exception
     // at second element (1)

let seq2 = Enumerable.range(0, 10);
seq2.assertAll((x) => {
    return x % 2 !== 1;
});  // will throw an aggregated exception
     // at the end
     // for all odd values

chunk []

let seq = Enumerable.range(0, 10);
for (let chunk of seq.chunk(3)) {
    // [0] => [0, 1, 2]
    // [1] => [3, 4, 5]
    // [2] => [6, 7, 8]
    // [3] => [9]
}

clone []

let father = Enumerable.create(0, 1, 2);

// create 3 clones of 'father'
for (let child of father.clone(3)) {
    //TODO
}

// alt: father.clone().take(3)

concat / concatArray []

// 0, 1, 2, 'PZ', 'TM', 'MK'
Enumerable.create(0, 1, 2)
          .concat(['PZ'], ['TM', 'MK']);  // alt: append()

// 0, 111, 222, 'pz', 'tm', 'mk'
Enumerable.create(0, 111, 222)
          .concatArray([ [ 'pz', 'tm' ], [ 'mk' ] ]);  // alt: appendArray()

consume []

function createIteratorAndStorage(size) {
    let storage = [];

    return {
        iterator: makeIterator(size, storage),
        storage: storage,
    };
}

function *makeIterator(size, storage) {
    for (let i = 0; i < size; i++) {
        yield i;

        storage.push(i);
    }
}

const OBJ = createIteratorAndStorage(100);

const SEQ = Enumerable.from(OBJ.iterator);
SEQ.consume();  // enumerates the 'iterator' in OBJ
                // and fills the 'storage' in OBJ

defaultIfEmpty / defaultArrayIfEmpty []

// 0, 1, 2
Enumerable.create(0, 1, 2)
          .defaultIfEmpty('PZ', 'TM', 'MK');
          
// 'PZ', 'TM', 'MK'
Enumerable.empty()
          .defaultIfEmpty('PZ', 'TM', 'MK');

// 0, 11, 22
Enumerable.create(0, 11, 22)
          .defaultArrayIfEmpty(['pz', 'tm', 'mk']);
// alt: defaultSequenceIfEmpty()

// 'pz', 'tm', 'mk'
Enumerable.empty()
          .defaultArrayIfEmpty(['pz', 'tm', 'mk']);

forAll []

let arr = [];

try {
    // alt: eachAll()
    Enumerable.range(0, 5).forAll(x => {
        if (x % 2 === 0) {
            throw 'Error in value ' + x;
        }

        arr.push(x);
    });
}
catch (e) {
    // access the list of errors by
    // 'e.errors'

    // e.errors[0] = 'Error in value 0';
    // e.errors[1] = 'Error in value 2';
    // e.errors[2] = 'Error in value 3';
}

// arr[0] === 1
// arr[1] === 3
// arr[2] === 5

intersperse / intersperseArray []

// 0, '-', 1, '-', 2
Enumerable.range(0, 3)
          .intersperse('-');

// -- or --
Enumerable.range(0, 3)
          .intersperseArray( ['-'] );

pipe []

let arr1 = [];
let arr2 = [];

let seq = Enumerable.create(1, 2, 3).pipe((x) => {
    arr1.push(x * 10);
});
for (let item of seq) {
    arr2.push(item);
}

// arr1 = [10, 20, 30]
// arr2 = [1, 2, 3]

popFrom / shiftFrom []

let arr1 = [ 11, 22, 33 ];
for (let item of Enumerable.popFrom(arr1)) {
    // [0] 33
    // [1] 22
    // [2] 11
}
// arr1 is empty now

let arr2 = [ 111, 222, 333 ];
for (let item of Enumerable.shiftFrom(arr2)) {
    // [0] 111
    // [1] 222
    // [2] 333
}
// arr2 is empty now

prepend / prependArray []

// 'PZ', 'TM', 'MK', 0, 1, 2
Enumerable.create(0, 1, 2)
          .prepend(['PZ'], ['TM', 'MK']);

// 'pz', 'tm', 'mk', 0, 111, 222
Enumerable.create(0, 111, 222)
          .prependArray([ [ 'pz', 'tm' ], [ 'mk' ] ]);

pushTo []

let arr = [];
Enumerable.create(0, 1, 2)
          .pushTo(arr);

// arr: [0, 1, 2]

random []

for (let value of Enumerable.random(10)) {
    // 10 random numbers
    // between 0 and 1
}

for (let value of Enumerable.random(23979,
                                    v => v * 5979)) {
    // 23979 random numbers
    // between 0 and 5979
}

reset []

let seq = Enumerable.create(0, 1, 2);

seq.each(x => {
             console.log(x);
         });

seq.reset()
   .each(x => {
             console.log(x * 2);
         });

trace []

// write items via 'console.trace()'
Enumerable.create(0, 1, 2)
          .trace();

// with formatter
Enumerable.create(1.2, 2.3, 3.45)
          .trace(x => 'Item: ' + x);

Documentation []

The API documentation can be found here.

License []

MIT license

Tests []

Go to the module folder and run

tsc
npm test

to start unit tests from test/ subfolder.

node-enumerable's People

Contributors

dependabot[bot] avatar mkloubert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

node-enumerable's Issues

Sequences are not reusable?

Based on the example on the REPL:

const seq = Enumerable.create(5979, 23979, null, '23979', 1781, 241279);

const a = seq.where((x) => x !== null)  // remove all elements that are (null)
   .skip(1)  // skip one element (5979)
   .take(3)  // take next remaining 3 elements (23979, 23979, 1781)
   .distinct()  // remove duplicates
   .select((x) => '' + x)
   .order();  // order by element ascending

const na = a.isEmpty();
a.toArray();

That returns an empty array.
Comment out the line const na = a.isEmpty(); and it returns the expected results.

Is this the expected behaviour, that the sequences are not query-able multiple times? I see the sequence object has a canReset property and this is false, is that related?

groupJoin produces empty result when inner is empty

groupJoin produces empty result when inner is empty. Let's see the following example.

const Enumerable = require("node-enumerable");

const persons = [
  { name: "Tanja" },
  { name: "Marcel" },
  { name: "Yvonne" },
  { name: "Josefine" }
];

const pets = [];

const e = Enumerable.from(persons)
  .groupJoin(
    pets, 
    person => person.name, 
    pet => pet.owner.name,
    (person, pets) => { person, pets }
  )
  .toArray();

Online runner
The example will result in an empty array [].

Expected result would be:

[
  { person: { name: "Tanja" }, pets: [] },
  { person: { name: "Marcel" }, pets: [] },
  { person: { name: "Yvonne" }, pets: [] },
  { person: { name: "Josefine" }, pets: [] }
]

Corresponding C# code produces the expected result.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
  public static void Main()
  {
    var people = new Person[]
    {
      new Person("Tanja"),
      new Person("Marcel"),
      new Person("Yvonne"),
      new Person("Josefine")
    };

    var pets = new Pet[0];

    var e = people.GroupJoin(
      pets, 
      person => person.Name, 
      pet => pet.Owner.Name,
      (person, ps) => new { Person = person, Pets = ps }
    ).ToArray();
  }
}

public class Person
{
  public string Name { get; set; }
  public Person(string name)
  {
    Name = name;
  }
}

public class Pet
{
  public string Name { get; set; }
  public Person Owner { get; set; }
  public Pet(string name, Person owner)
  {
    Name = name;
    Owner = owner;
  }
}

Calling IEnumerable.count() twice gets different results

Here is the code I use to reproduce the issue.

const Enumerable = require("node-enumerable");
const assert = require("assert");
const data = Enumerable.from([1, 2, 3, 4, 5]);
assert.equal(data.count(), data.count());

The code above throws an assertion error.

AssertionError: 5 == 0

Environment

  • node v6.11.2
  • node-enumerable v3.6.0

Is it expected?
Thanks in advance! 😃

Typescript semantic error: A type predicate's type must be assignable to its parameter's type

This comes from the index.d.ts, specifically these 3 functions:

function isNullOrEmpty<T>(seq: IEnumerable<T>): seq is (null | IEnumerable<T>);
function isUndefinedNullOrEmpty<T>(seq: IEnumerable<T>): seq is (undefined | null | IEnumerable<T>);
function isUndefinedOrEmpty<T>(seq: IEnumerable<T>): seq is (undefined | IEnumerable<T>);

I believe the correct semantics, also based on their names and what they should be able to accept as parameters is:

function isNullOrEmpty<T>(seq: null | IEnumerable<T>): seq is (null | IEnumerable<T>);
function isUndefinedNullOrEmpty<T>(seq: undefined | null | IEnumerable<T>): seq is (undefined | null | IEnumerable<T>);
function isUndefinedOrEmpty<T>(seq: undefined | IEnumerable<T>): seq is (undefined | IEnumerable<T>);

I am using typescript 2.7.2.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.