FrancescoLorenzetti84 FrancescoLorenzetti84 - 2 months ago 7
TypeScript Question

Passing an Expression as a parameter of a filter function in Typescript

Consider the following Typescript function:

getPeople(): Person[] {
return model.people;
}


I'd like to implement it with an embedded filter, which will work based on an Expression that I want to pass as a parameter, more or less like this:

getPeopleBy(expression): Person[] {
return model.people.filter(expression);
}

var filteredPeople = getPeopleBy(p => p.age < 30);


With Linq and C#, I can do it by accepting a parameter with this syntaxis
Expression<Func<EcommerceProduct, bool>> filter


Is there anything similar in Typescript / Javascript?

Answer

Disregard (initial answer - leaving it here so people understand the evolution process):

Yes, in C# you can do this, but you have to remember TypeScript comes with some sugar syntax that borrows from C#, JavaScript is it's own animal.

In order to pass an expression, you need to remember that a lamba expression is just a function, so in JS you just have, keys, values (objects) and functions (simple, right?).

So to achieve what you want your code should look like this:

getPeopleBy(expression: Function): Person[] {
    return model.people.filter(expression);
}

var filteredPeople = getPeopleBy((p: Person) => { return p.age < 30 });

PS: may I also recommend you change the function name to getPeopleWith?

as you can see, from a human perspective, it makes much more sense to read:

getPeopleWith((p: Person) => { return p.age < 30 });

Basically it's get the people with the age less than 30, easily readable by any person :)

Update:

This will offer you the desired result!

TypeScript Playground Example

class People {
    private static people: any[] = [];

    static where(expression: (value: any, index?: number, Array?: any[]) => boolean): 
                                                                            any[] {
        return this.people.filter(expression);
    }
}


People.where(p => p.age < 30);

Update 2:

TypeScript Playground Example using interface definition for callback

If you need to write a FluentAPI or something bigger and you're tired of dragging along the callbackfn definition, you can also do something like this:

interface IFilter {
    value: any;
    index?: number;
    Array?: any[];
}

class People {
    private static people: any[];

    static where(expression: (IFilter) => boolean): any[] {
        return this.people.filter(expression);
    }
}


People.where(p => p.age < 30);

Update 3:

TypeScript Playground with Type Inference

And with this you can also get nice IntelliSense, by using templates in the interface :)

interface Person {
    age: number;
}

interface IFilter<T> {
    value: T;
    index?: number;
    Array?: T[];
}

class People {
    private static people: Person[];

    static where(expression: (IFilter: Person) => boolean): any[] {
        return this.people.filter(expression);
    }
}

People.where(p => p.age < 30); 

I hope these series of updates help you achieve your goals.