Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd33da8

Browse files
authored
Types/improve operator node types (josdejong#2576)
* Add generic args to OperatorNode for `fn` and `op` * Fix lint * Format and add generic for args as well * Make OperatorNode generics optional using `never`
1 parent 717dd32 commit cd33da8

2 files changed

Lines changed: 77 additions & 17 deletions

File tree

types/index.d.ts

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,25 +276,67 @@ declare namespace math {
276276
new (properties: Record<string, MathNode>): ObjectNode
277277
}
278278

279-
interface OperatorNode extends MathNodeCommon {
279+
type OperatorNodeMap = {
280+
xor: 'xor'
281+
and: 'and'
282+
bitOr: '|'
283+
bitXor: '^|'
284+
bitAnd: '&'
285+
equal: '=='
286+
unequal: '!='
287+
smaller: '<'
288+
larger: '>'
289+
smallerEq: '<='
290+
leftShift: '<<'
291+
rightArithShift: '>>'
292+
rightLogShift: '>>>'
293+
to: 'to'
294+
add: '+'
295+
subtract: '-'
296+
multiply: '*'
297+
divide: '/'
298+
dotMultiply: '.*'
299+
dotDivide: './'
300+
mod: 'mod'
301+
unaryPlus: '+'
302+
unaryMinus: '-'
303+
bitNot: '~'
304+
not: 'not'
305+
pow: '^'
306+
dotPow: '.^'
307+
factorial: '!'
308+
}
309+
310+
type OperatorNodeOp = OperatorNodeMap[keyof OperatorNodeMap]
311+
type OperatorNodeFn = keyof OperatorNodeMap
312+
313+
interface OperatorNode<
314+
TOp extends OperatorNodeMap[TFn] = never,
315+
TFn extends OperatorNodeFn = never,
316+
TArgs extends MathNode[] = MathNode[]
317+
> extends MathNodeCommon {
280318
type: 'OperatorNode'
281319
isOperatorNode: true
282-
op: string
283-
fn: string
284-
args: MathNode[]
320+
op: TOp
321+
fn: TFn
322+
args: TArgs
285323
implicit: boolean
286324
isUnary(): boolean
287325
isBinary(): boolean
288326
}
289-
interface OperatorNodeCtor {
290-
new (
291-
op: string,
292-
fn: string,
293-
args: MathNode[],
327+
328+
interface OperatorNodeCtor extends MathNodeCommon {
329+
new <
330+
TOp extends OperatorNodeMap[TFn],
331+
TFn extends OperatorNodeFn,
332+
TArgs extends MathNode[]
333+
>(
334+
op: TOp,
335+
fn: TFn,
336+
args: TArgs,
294337
implicit?: boolean
295-
): OperatorNode
338+
): OperatorNode<TOp, TFn, TArgs>
296339
}
297-
298340
interface ParenthesisNode extends MathNodeCommon {
299341
type: 'ParenthesisNode'
300342
isParenthesisNode: true
@@ -345,7 +387,7 @@ declare namespace math {
345387
| FunctionNode
346388
| IndexNode
347389
| ObjectNode
348-
| OperatorNode
390+
| OperatorNode<OperatorNodeOp, OperatorNodeFn>
349391
| ParenthesisNode
350392
| RangeNode
351393
| RelationalNode
@@ -3095,7 +3137,9 @@ declare namespace math {
30953137

30963138
isObjectNode(x: unknown): x is ObjectNode
30973139

3098-
isOperatorNode(x: unknown): x is OperatorNode
3140+
isOperatorNode(
3141+
x: unknown
3142+
): x is OperatorNode<OperatorNodeOp, OperatorNodeFn>
30993143

31003144
isParenthesisNode(x: unknown): x is ParenthesisNode
31013145

types/index.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import {
2525
MathNumericType,
2626
ConstantNode,
2727
OperatorNode,
28+
OperatorNodeFn,
29+
OperatorNodeOp,
30+
SymbolNode,
2831
} from 'mathjs'
2932
import * as assert from 'assert'
3033
import { expectTypeOf } from 'expect-type'
@@ -1527,23 +1530,34 @@ Function round examples
15271530
*/
15281531
{
15291532
const math = create(all, {})
1533+
expectTypeOf(
1534+
new math.OperatorNode('/', 'divide', [
1535+
new math.ConstantNode(3),
1536+
new math.SymbolNode('x'),
1537+
])
1538+
).toMatchTypeOf<OperatorNode<'/', 'divide', (ConstantNode | SymbolNode)[]>>()
1539+
15301540
expectTypeOf(new math.ConstantNode(1).clone()).toMatchTypeOf<ConstantNode>()
15311541
expectTypeOf(
15321542
new math.OperatorNode('*', 'multiply', [
15331543
new math.ConstantNode(3),
15341544
new math.SymbolNode('x'),
15351545
]).clone()
1536-
).toMatchTypeOf<OperatorNode>()
1546+
).toMatchTypeOf<
1547+
OperatorNode<'*', 'multiply', (ConstantNode | SymbolNode)[]>
1548+
>()
15371549

15381550
expectTypeOf(
15391551
new math.ConstantNode(1).cloneDeep()
15401552
).toMatchTypeOf<ConstantNode>()
15411553
expectTypeOf(
1542-
new math.OperatorNode('*', 'multiply', [
1554+
new math.OperatorNode('+', 'unaryPlus', [
15431555
new math.ConstantNode(3),
15441556
new math.SymbolNode('x'),
15451557
]).cloneDeep()
1546-
).toMatchTypeOf<OperatorNode>()
1558+
).toMatchTypeOf<
1559+
OperatorNode<'+', 'unaryPlus', (ConstantNode | SymbolNode)[]>
1560+
>()
15471561

15481562
expectTypeOf(
15491563
math.clone(new math.ConstantNode(1))
@@ -1900,7 +1914,9 @@ Factory Test
19001914
expectTypeOf(x).toMatchTypeOf<math.ObjectNode>()
19011915
}
19021916
if (math.isOperatorNode(x)) {
1903-
expectTypeOf(x).toMatchTypeOf<math.OperatorNode>()
1917+
expectTypeOf(x).toMatchTypeOf<
1918+
OperatorNode<OperatorNodeOp, OperatorNodeFn, MathNode[]>
1919+
>()
19041920
}
19051921
if (math.isParenthesisNode(x)) {
19061922
expectTypeOf(x).toMatchTypeOf<math.ParenthesisNode>()

0 commit comments

Comments
 (0)