, JavaScript .
, a => "a.Scope == 'Framework'", , /- , .
, (eval) , , , , , , .
, , , , JavaScript, TypeScript .
export interface MemberInvocationExpression {
kind: 'memberInvocation';
memberKey: keyof Project;
args?: {}[];
negated?: true;
conjunction: 'and' | 'or';
};
export interface MemberComparisonExpression {
kind: 'memberComparison';
memberKey: keyof Project;
compareWith: {};
negated?: true;
comparison: 'equal' | 'notEqual' | 'greater' | 'lesser';
conjunction: 'and' | 'or';
}
export type GridFilterExpression =
| MemberInvocationExpression
| MemberComparisonExpression;
export default class {
gridFilterExpressions: GridFilterExpression[] = [];
composeFilters(): (p: Project) => boolean {
return this.gridFilterExpressions.reduce((composed, expression) => {
const conjunction = expression.conjunction;
const predicate = predicateFromExpression(expression);
switch (conjunction) {
case 'and':
return p => composed(p) && predicate(p);
case 'or':
return p => composed(p) || predicate(p);
default:
throw Error('Invalid composition');
}
}, _ => true);
}
}
function predicateFromExpression(expression: GridFilterExpression) {
switch (expression.kind) {
case 'memberInvocation':
return predicateFromMemberInvocationExpression(expression);
case 'memberComparison':
return predicateFromMemberComparisonExpression(expression);
case
default: throw Error('invalid filter');
}
}
function predicateFromMemberInvocationExpression(expression: MemberInvocationExpression) {
const {memberKey, args, negated} = expression;
const predicate = (p: Project) => p[memberKey](...args);
return negated ? (p: Project) => !predicate(p) : predicate;
}
function predicateFromMemberComparisonExpression(expression: MemberComparisonExpression) {
const {memberKey, compareWith, comparison, negated} = expression;
const predicate = (p: Project) => {
switch (comparison) {
case 'equal': return p[memberKey] === compareWith;
case 'notEqual': return p[memberKey] !== compareWith;
case 'greater': return p[memberKey] > compareWith;
case 'lesser': return p[memberKey] < compareWith;
default: throw Error('Invalid comparison in filter');
}
};
return negated ? (p: Project) => !predicate(p) : predicate;
}
, gridFilterExpressions , , , .
, , :
gridFilterExpressions
.push({
memberKey: 'Scope',
compareWith: 'framework',
comparison: 'equal',
conjunction: 'and'
},
{
kind: 'memberInvocation',
memberKey: 'endsWith',
args: ['test'],
conjunction: 'or'
});