Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to extend Enumerable (IEnumerable?) #99

Open
juancri opened this issue Dec 8, 2022 · 4 comments
Open

How to extend Enumerable (IEnumerable?) #99

juancri opened this issue Dec 8, 2022 · 4 comments

Comments

@juancri
Copy link

juancri commented Dec 8, 2022

I'm extending Array<T> using this technique.

A silly example:

declare global {
    interface Array<T> {
        remove(o: T): Array<T>;
    }
}

Array.prototype.remove = function (o) {
    // code to remove "o"
    return this;
}

Is there any recommended way to do the same with Enumerable / IEnumerable?

I think the challenge here is to extend the interface, which is the return type of Enumerable methods.

Part 2: Include non-standard methods

If extension is not possible, what about adding non-standard LINQ methods to the library? I'm thinking about methods like takeUntilIncluding, which includes the first item that matches the predicate as well (example).

@mihaifm
Copy link
Owner

mihaifm commented Dec 9, 2022

You can add stuff to the Enumerable prototype, I don't see why not.

You can check the code to see how other prototype methods are implemented:

linq/linq.js

Line 2097 in 45a45fb

Enumerable.prototype.takeExceptLast = function (count) {

@jeremyliseismic
Copy link

jeremyliseismic commented Jan 13, 2023

@mihaifm Custom prototype functions can be added properly into a js file, just like you said.
However, I don't know how to add them into a ts file. When I tried to do that, I got a compile error
Property 'prototype' does not exist on type 'typeof Enumerable'.ts(2339)

// linq-ext.ts
import Enumerable from 'linq'

Enumerable.prototype.whereIf = function <T>(flag: boolean, filter: (t: T) => boolean) {
  return flag ? this.where(filter) : this;
}
declare global {
  export interface Enumerable {
    whereIf<T>(flag: boolean, filter: (t: T) => boolean): Enumerable.IEnumerable<T>;
  }
}

Do you know how to achieve that?

@juancri
Copy link
Author

juancri commented Jan 13, 2023

Forgot to comment, but yeah... same problem I'm having :D

@jeremyliseismic
Copy link

jeremyliseismic commented Feb 3, 2023

@juancri I found a workaround and it also works for linq.js with ts.
microsoft/TypeScript#14080 (comment)
(NOTE: as mentioned in its reply, it may bring conflict into your project.)

To my understanding, the reason why we cannot extend linq.js with ts directly is that the namespace Enumerable is exported as default.

linq/linq.d.ts

Line 237 in 45a45fb

export default Enumerable;

@mihaifm So is it possible to add export Enumerable; into linq.d.ts for easily extending? Or is there better solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants