-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Description
First I would like to say that I don't want to overwhelm those who are diligently making TypeScript a reality. I really appreciate this project. I also believe TypeScript is the future.
The company that I work for deals with a lot of data. In order to deal with this need we built a DbContext (Entitites in C#) for javascript. We also built Queryables (Linq in C#) backed by Expressions Trees for javascript. This has been very useful, and all of our programs today are using this technology. The problem is that today our syntax for this is a bit wonky. Here is what the syntax looks like today.
dbContext.people.asQueryable().filter(function(e){
return e.property(“firstName”).isEqualTo(“Jared”);
});It gets worse with “AND”s and “OR”s.
dbContext.people.asQueryable().filter(function(e){
return e.and(e.property(“firstName”).isEqualTo(“Jared”), e.property(“lastName”).isEqualTo(“Barnes”));
});Our wish is that we could have the filter function look like we were acting on local data with Array.prototype.filter.
dbContext.people.asQueryable().filter(function(person: Person){
return person.firstName == “Jared” && person.lastName == “Barnes”;
});Or even better would be.
dbContext.people.asQueryable().filter((person: Person) => {
return person.firstName == “Jared” && person.lastName == “Barnes”;
});So here is what I would propose to answer this problem in TypeScript. I would like feedback and open discussion about this. I don’t think that I have all the answers, so please tell me if I’m completely misguided.
I like the idea that we could have a get Property on a function that would return the expression tree representing the function. If we do this, we have the function that could be used to filter local arrays as well as the expression tree (Abstract Syntax Tree) to filter remote data. Here is how it would look.
var fn = (person: Person) => {
return person.firstName == “Jared”;
};
// Now I can turn this into anything I want. Odata, SQL you name it.
var expressionTree = fn.expression;
someArray.filter(fn);
dbContext.people.asQueryable().filter(fn).toArray().then((array)=>{
// Do somthing.
});The problem with this approach is that every function would be unnecessarily bloated with this Expression Tree. My thought was maybe we could create a syntax for Lamda Expressions. That way would could only have the bloat when it's necessary.
Should the syntax be like C#’s?
person:Person => person.firstName == “Jared”;I have already hacked the ArrowFunctionExpression to do it for our company today. But I think that it would be better if I had more feedback on how others would like it, or if they would like lambdas at all. I also don’t want to have it on the ArrowFunctionExpression because I find myself using this syntax because its a better way to describe a function anyways (less verbose). Not to mention that its made it into the javascript spec.
On a deeper note this is how its compiled today for us.
Typescript:
var fn = (person: Person) => {
return person.firstName == “Jared”;
};Javascript:
var fn = (function(){
var _fn = function(person){
return person.firstName == “Jared”;
};
var _scopeInspector = function(variableName){
return eval(variableName);
};
// The ExpressionTree needs a way to access
// scoped variables found in the expression tree.
// This is why we are using the evil eval.
// expressionJSON is generated from the AST during compilation.
var expTree = new ExpressionTree(_scopeInspector, expressionJSON );
Object.defineProperty(_fn, “expression”, {
get: function(){
return expTree;
}
});
return _fn;
}());If you made it this far, thank you for reading.
And please share your ideas.