Skip to content

Commit

Permalink
Added helper type for describing the allowed properties of the expres…
Browse files Browse the repository at this point in the history
…sion
  • Loading branch information
regevbr committed Mar 9, 2021
1 parent 350a9dd commit 88105f0
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "json-expression-eval",
"version": "3.2.0",
"version": "3.3.0",
"description": "evaluate a json described boolean expression using dynamic functions",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
8 changes: 7 additions & 1 deletion src/example/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,22 @@ run(expression, context);

const evaluator = getEvaluator(expression);

const expressionParts: GetExpressionParts<typeof evaluator> = {
const expressionParts: GetExpressionParts<typeof evaluator, { description: string }> = {
nested: {
value: {
isArray: false,
isFunction: false,
propertyPath: 'nested.value',
type: 'number',
description: 'my desc',
},
nested2: {
value: {
isArray: false,
isFunction: false,
propertyPath: 'nested.nested2.value',
type: 'number',
description: 'my desc',
},
},
},
Expand All @@ -124,23 +126,27 @@ const expressionParts: GetExpressionParts<typeof evaluator> = {
isFunction: false,
propertyPath: 'times',
type: 'number',
description: 'my desc',
},
userId: {
isArray: false,
isFunction: false,
propertyPath: 'userId',
type: 'string',
description: 'my desc',
},
maxCount: {
isArray: false,
isFunction: true,
propertyPath: 'maxCount',
type: 'number',
description: 'my desc',
},
user: {
isArray: false,
isFunction: true,
propertyPath: 'user',
type: 'string',
description: 'my desc',
},
} as const;
18 changes: 9 additions & 9 deletions src/expressionParts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ interface ExpressionFunctionPart<C extends Context, F extends FunctionsTable<C>,
isFunction: true;
}

type ExpressionFunctionParts<C extends Context, F extends FunctionsTable<C>> = {
[K in keyof F]: ExpressionFunctionPart<C, F, K>
type ExpressionFunctionParts<C extends Context, F extends FunctionsTable<C>, Extra extends object> = {
[K in keyof F]: ExpressionFunctionPart<C, F, K> & Extra;
}

interface ExpressionContextPart<C extends Context, K extends keyof C, P extends List.List<string>> {
Expand All @@ -25,15 +25,15 @@ interface ExpressionContextPart<C extends Context, K extends keyof C, P extends

type Primitive = string | number | boolean;

type _ExpressionContextParts<C, P extends List.List<string>> = {
type _ExpressionContextParts<C, P extends List.List<string>, Extra extends object> = {
[k in U.Select<keyof C, string>]:
C[k] extends Primitive ? ExpressionContextPart<C, k, [...P, k]>
C[k] extends Primitive ? ExpressionContextPart<C, k, [...P, k]> & Extra
: C[k] extends Array<any> ? never
: _ExpressionContextParts<C[k], [...P, k]>;
: _ExpressionContextParts<C[k], [...P, k], Extra>;
}

type ExpressionContextParts<C extends Context> = _ExpressionContextParts<C, []>;
type ExpressionContextParts<C extends Context, Extra extends object> = _ExpressionContextParts<C, [], Extra>;

export type ExpressionParts<C extends Context, F extends FunctionsTable<C>> =
ExpressionFunctionParts<C, F>
& ExpressionContextParts<C>;
export type ExpressionParts<C extends Context, F extends FunctionsTable<C>, Extra extends object = {}> =
ExpressionFunctionParts<C, F, Extra>
& ExpressionContextParts<C, Extra>;
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ export class ExpressionEval<C extends Context, F extends FunctionsTable<C>> {

}

export type GetExpressionParts<E extends ExpressionEval<any, any>> =
E extends ExpressionEval<infer C, infer F> ? ExpressionParts<C, F> : never;
export type GetExpressionParts<E extends ExpressionEval<any, any>, Extra extends object = {}> =
E extends ExpressionEval<infer C, infer F> ? ExpressionParts<C, F, Extra> : never;
88 changes: 88 additions & 0 deletions src/test/expressionParts.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,94 @@ const expected = {
},
} as const;

type ResultExtended =
O.Readonly<ExpressionParts<ExpressionContext, ExpressionFunction, { description: string }>, Any.Key, 'deep'>;

const expectedExtended = {
nested: {
value: {
isArray: false,
isFunction: false,
propertyPath: 'nested.value',
type: 'number',
description: 'my desc' as string,
},
nested2: {
value: {
isArray: false,
isFunction: false,
propertyPath: 'nested.nested2.value',
type: 'string',
description: 'my desc' as string,
},
},
},
str: {
isArray: false,
isFunction: false,
propertyPath: 'str',
type: 'string',
description: 'my desc' as string,
},
strFn: {
isArray: false,
isFunction: true,
propertyPath: 'strFn',
type: 'string',
description: 'my desc' as string,
},
strArrFn: {
isArray: true,
isFunction: true,
propertyPath: 'strArrFn',
type: 'string',
description: 'my desc' as string,
},
num: {
isArray: false,
isFunction: false,
propertyPath: 'num',
type: 'number',
description: 'my desc' as string,
},
numFn: {
isArray: false,
isFunction: true,
propertyPath: 'numFn',
type: 'number',
description: 'my desc' as string,
},
numArrFn: {
isArray: true,
isFunction: true,
propertyPath: 'numArrFn',
type: 'number',
description: 'my desc' as string,
},
bool: {
isArray: false,
isFunction: false,
propertyPath: 'bool',
type: 'boolean',
description: 'my desc' as string,
},
boolFn: {
isArray: false,
isFunction: true,
propertyPath: 'boolFn',
type: 'boolean',
description: 'my desc' as string,
},
boolArrFn: {
isArray: true,
isFunction: true,
propertyPath: 'boolArrFn',
type: 'boolean',
description: 'my desc' as string,
},
} as const;

Test.checks([
Test.check<Result, typeof expected, Test.Pass>(),
Test.check<ResultExtended, typeof expectedExtended, Test.Pass>(),
]);

0 comments on commit 88105f0

Please sign in to comment.