mihaifm / linq

linq.js - LINQ for JavaScript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect Enumerable type when object contains length property

eJuke opened this issue · comments

Hello
I tried to use your library with objects with this structure:

const vehicle = {
    weight: 1000,
    length: 5,
    color: "Blue",
    ...
}

and wanted to filter some values using .where method

Enumerable.from(vehicle)
    .where(i => excludedFields.indexOf(i.Key) == -1)
    .toObject(i => i.Key, i => i.Value);

I expected that .from function would convert my object to KeyValuePair. Unfortunately this method considered that input is array and didn't convert object to KeyValue

I checked the source code and found this statement on the row 300

// array or array like object
if (typeof obj.length == Types.Number) {
    return new ArrayEnumerable(obj);
}

It looks like any object with length property will be converted to ArrayEnumerable independent of another properties.
Is it possible to check for Arrays by another way (something like instanceof call)?

Good find, I don't think we need to keep that logic. I would change it to Array.isArray(obj), but need to check potential problems.

I've done some tests and it seems like this change is not a good idea. Using Array.isArray(obj) (or instanceof ) instead of typeof obj.length == Types.Number would exclude array-like objects, most notably the arguments object and return values from DOM functions like document.getElementsByTagName() that return a list of elements.

You can consider this issue a small limitation of the library, but it's probably better to change the name of your length property to avoid other problems down the line.

Also a small correction to your code, when converting to object use .toObject(i => i.key, i => i.value); (without the capitalization)

Is it possible to create method .fromObject or something like this?
We cannot change name of length property because we have too many models with this property. So renaming will take too much time to support it across the system.

commented

I think it would be odd to create a separate method for such a narrow use-case.

But you can of course create your own helper method which will transform your object to an array of key-value pairs.

Thank you for your response
I created local module with Enumerable extension (patch adds .fromObject method) and updated linq module to have type definition for the new method. It's suitable for me