simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

index.ts (20776B)


      1 import {
      2   create,
      3   factory,
      4   all,
      5   MathJsFunctionName,
      6   fractionDependencies,
      7   addDependencies,
      8   divideDependencies,
      9   formatDependencies,
     10 } from 'mathjs';
     11 import * as assert from 'assert';
     12 import { expectTypeOf } from 'expect-type'
     13 
     14 // This file serves a dual purpose:
     15 // 1) examples of how to use math.js in TypeScript
     16 // 2) tests for the TypeScript declarations provided by math.js
     17 
     18 /*
     19 Basic usage examples
     20 */
     21 {
     22   const math = create(all);
     23 
     24   // functions and constants
     25   math.round(math.e, 3);
     26   math.round(100.123, 3);
     27   math.atan2(3, -3) / math.pi;
     28   math.log(10000, 10);
     29   math.sqrt(-4);
     30   math.pow([[-1, 2], [3, 1]], 2);
     31   const angle = 0.2;
     32   math.add(math.pow(math.sin(angle), 2), math.pow(math.cos(angle), 2));
     33 
     34   // std and variance check
     35   math.std(1, 2, 3)
     36   math.std([1, 2, 3])
     37   math.std([1, 2, 3], "biased")
     38   math.std([1,2, 3], 0, "biased")
     39   math.std([[1,2,3], [4,5,6]], 1, "unbiased")
     40   math.std([[1,2,3], [4,5,6]], 1, "uncorrected")
     41   math.variance(1, 2, 3)
     42   math.variance([1, 2, 3])
     43   math.variance([1, 2, 3], "biased")
     44   math.variance([1,2, 3], 0, "biased")
     45   math.variance([[1,2,3], [4,5,6]], 1, "unbiased")
     46   math.variance([[1,2,3], [4,5,6]], 1, "uncorrected")
     47 
     48   // std and variance on chain
     49   math.chain([1, 2, 3]).std("unbiased")
     50   math.chain([[1, 2, 3], [4, 5, 6]]).std(0, "biased").std(0, "uncorrected")
     51   math.chain([[1, 2, 3], [4, 5, 6]]).std(0, "biased").std(0, "uncorrected")
     52   math.chain([1, 2, 3]).std("unbiased")
     53   math.chain([[1, 2, 3], [4, 5, 6]]).variance(0, "biased")
     54   math.chain([[1, 2, 3], [4, 5, 6]]).variance(1, "uncorrected").variance("unbiased")
     55 
     56 
     57   // expressions
     58   math.evaluate('1.2 * (2 + 4.5)');
     59 
     60   // chained operations
     61   const a = math.chain(3).add(4).multiply(2).done();
     62   assert.strictEqual(a, 14);
     63 
     64   // mixed use of different data types in functions
     65   assert.deepStrictEqual(math.add(4, [5, 6]), [9, 10]); // number + Array
     66   assert.deepStrictEqual(math.multiply(math.unit('5 mm'), 3), math.unit('15 mm')); // Unit * number
     67   assert.deepStrictEqual(math.subtract([2, 3, 4], 5), [-3, -2, -1]); // Array - number
     68   assert.deepStrictEqual(math.add(math.matrix([2, 3]), [4, 5]), math.matrix([6, 8])); // Matrix + Array
     69 
     70   // narrowed type inference
     71   const b: math.Matrix = math.add(math.matrix([2]), math.matrix([3]));
     72   const c: math.Matrix = math.subtract(math.matrix([4]), math.matrix([5]));
     73 }
     74 
     75 /*
     76 Bignumbers examples
     77 */
     78 {
     79   // configure the default type of numbers as BigNumbers
     80   const math = create(all, {
     81     number: 'BigNumber',
     82     precision: 20,
     83   });
     84 
     85   {
     86     assert.deepStrictEqual(math.add(math.bignumber(0.1), math.bignumber(0.2)), math.bignumber(0.3));
     87     assert.deepStrictEqual(math.divide(math.bignumber(0.3), math.bignumber(0.2)), math.bignumber(1.5));
     88   }
     89 }
     90 
     91 /*
     92 Chaining examples
     93 */
     94 {
     95   const math = create(all, {});
     96   const a = math.chain(3).add(4).multiply(2).done();
     97   assert.strictEqual(a, 14);
     98 
     99   // Another example, calculate square(sin(pi / 4))
    100   const b = math.chain(math.pi).divide(4).sin().square().done();
    101 
    102   // toString will return a string representation of the chain's value
    103   const chain = math.chain(2).divide(3);
    104   const str: string = chain.toString();
    105   assert.strictEqual(str, "0.6666666666666666");
    106 
    107   chain.valueOf();
    108 
    109   // the function subset can be used to get or replace sub matrices
    110   const array = [
    111     [1, 2],
    112     [3, 4],
    113   ];
    114   const v = math.chain(array).subset(math.index(1, 0)).done();
    115   assert.strictEqual(v, 3);
    116 
    117   const m = math.chain(array).subset(math.index(0, 0), 8).multiply(3).done();
    118 
    119   // filtering
    120   assert.deepStrictEqual(
    121     math
    122       .chain([-1, 0, 1.1, 2, 3, 1000])
    123       .filter(math.isPositive)
    124       .filter(math.isInteger)
    125       .filter((n) => n !== 1000)
    126       .done(),
    127     [2, 3]
    128   );
    129 }
    130 
    131 /*
    132 Simplify examples
    133 */
    134 {
    135   const math = create(all);
    136 
    137   math.simplify("2 * 1 * x ^ (2 - 1)");
    138   math.simplify("2 * 3 * x", { x: 4 });
    139 
    140   const f = math.parse("2 * 1 * x ^ (2 - 1)");
    141   math.simplify(f);
    142 
    143   math.simplify("0.4 * x", {}, { exactFractions: true });
    144   math.simplify("0.4 * x", {}, { exactFractions: false });
    145 }
    146 
    147 /*
    148 Complex numbers examples
    149 */
    150 {
    151   const math = create(all, {});
    152   const a = math.complex(2, 3);
    153   // create a complex number by providing a string with real and complex parts
    154   const b = math.complex('3 - 7i');
    155 
    156   // read the real and complex parts of the complex number
    157   {
    158     const x: number = a.re;
    159     const y: number = a.im;
    160 
    161     // adjust the complex value
    162     a.re = 5;
    163   }
    164 
    165   // clone a complex value
    166   {
    167     const clone = a.clone();
    168   }
    169 
    170   // perform operations with complex numbers
    171   {
    172     math.add(a, b);
    173     math.multiply(a, b);
    174     math.sin(a);
    175   }
    176 
    177   // create a complex number from polar coordinates
    178   {
    179     const p: math.PolarCoordinates = { r: math.sqrt(2), phi: math.pi / 4 };
    180     const c: math.Complex = math.complex(p);
    181   }
    182 
    183   // get polar coordinates of a complex number
    184   {
    185     const p: math.PolarCoordinates = math.complex(3, 4).toPolar();
    186   }
    187 }
    188 
    189 /*
    190 Expressions examples
    191 */
    192 {
    193   const math = create(all, {});
    194   // evaluate expressions
    195   {
    196     math.evaluate('sqrt(3^2 + 4^2)');
    197   }
    198 
    199   // evaluate multiple expressions at once
    200   {
    201     math.evaluate(['f = 3', 'g = 4', 'f * g']);
    202   }
    203 
    204   // get content of a parenthesis node
    205   {
    206     const node = math.parse('(1)');
    207     if (node.type !== 'ParenthesisNode') {
    208       throw Error(`expected ParenthesisNode, got ${node.type}`);
    209     }
    210     const innerNode = node.content;
    211   }
    212 
    213   // scope can contain both variables and functions
    214   {
    215     const scope = { hello: (name: string) => `hello, ${name}!` };
    216     assert.strictEqual(math.evaluate('hello("hero")', scope), "hello, hero!");
    217   }
    218 
    219   // define a function as an expression
    220   {
    221     const scope: any = {
    222       a: 3,
    223       b: 4,
    224     };
    225     const f = math.evaluate('f(x) = x ^ a', scope);
    226     f(2);
    227     scope.f(2);
    228   }
    229 
    230   {
    231     const node2 = math.parse('x^a');
    232     const code2: math.EvalFunction = node2.compile();
    233     node2.toString();
    234   }
    235 
    236   // 3. using function math.compile
    237   // parse an expression
    238   {
    239     // provide a scope for the variable assignment
    240     const code2 = math.compile('a = a + 3');
    241     const scope = { a: 7 };
    242     code2.evaluate(scope);
    243   }
    244   // 4. using a parser
    245   const parser = math.parser();
    246 
    247   // get and set variables and functions
    248   {
    249     assert.strictEqual(parser.evaluate('x = 7 / 2'), 3.5);
    250     assert.strictEqual(parser.evaluate('x + 3'), 6.5);
    251     parser.evaluate('f(x, y) = x^y'); // f(x, y)
    252     assert.strictEqual(parser.evaluate('f(2, 3)'), 8);
    253 
    254     const x = parser.get('x');
    255     const f = parser.get('f');
    256     const y = parser.getAll();
    257     const g = f(3, 3);
    258 
    259     parser.set('h', 500);
    260     parser.set('hello', (name: string) => `hello, ${name}!`);
    261   }
    262 
    263   // clear defined functions and variables
    264   parser.clear();
    265 }
    266 
    267 /*
    268 Fractions examples
    269 */
    270 {
    271   // configure the default type of numbers as Fractions
    272   const math = create(all, {
    273     number: 'Fraction',
    274   });
    275 
    276   const x = math.fraction(0.125);
    277   const y = math.fraction('1/3');
    278   math.fraction(2, 3);
    279 
    280   math.add(x, y);
    281   math.divide(x, y);
    282 
    283   // output formatting
    284   const a = math.fraction('2/3');
    285 }
    286 
    287 /*
    288 Matrices examples
    289 */
    290 {
    291   const math = create(all, {});
    292 
    293   // create matrices and arrays. a matrix is just a wrapper around an Array,
    294   // providing some handy utilities.
    295   const a: math.Matrix = math.matrix([1, 4, 9, 16, 25]);
    296   const b: math.Matrix = math.matrix(math.ones([2, 3]));
    297   b.size();
    298 
    299   // the Array data of a Matrix can be retrieved using valueOf()
    300   const array = a.valueOf();
    301 
    302   // Matrices can be cloned
    303   const clone: math.Matrix = a.clone();
    304 
    305   // perform operations with matrices
    306   math.sqrt(a);
    307   math.factorial(a);
    308 
    309   // create and manipulate matrices. Arrays and Matrices can be used mixed.
    310   {
    311     const a = [
    312       [1, 2],
    313       [3, 4],
    314     ];
    315     const b: math.Matrix = math.matrix([
    316       [5, 6],
    317       [1, 1],
    318     ]);
    319 
    320     b.subset(math.index(1, [0, 1]), [[7, 8]]);
    321     const c = math.multiply(a, b);
    322     const f: math.Matrix = math.matrix([1, 0]);
    323     const d: math.Matrix = f.subset(math.index(1));
    324   }
    325 
    326   // get a sub matrix
    327   {
    328     const a: math.Matrix = math.diag(math.range(1, 4));
    329     a.subset(math.index([1, 2], [1, 2]));
    330     const b: math.Matrix = math.range(1, 6);
    331     b.subset(math.index(math.range(1, 4)));
    332   }
    333 
    334   // resize a multi dimensional matrix
    335   {
    336     const a = math.matrix();
    337     a.resize([2, 2, 2], 0);
    338     a.size();
    339     a.resize([2, 2]);
    340     a.size();
    341   }
    342 
    343   // can set a subset of a matrix to uninitialized
    344   {
    345     const m = math.matrix();
    346     m.subset(math.index(2), 6, math.uninitialized);
    347   }
    348 
    349   // create ranges
    350   {
    351     math.range(1, 6);
    352     math.range(0, 18, 3);
    353     math.range('2:-1:-3');
    354     math.factorial(math.range('1:6'));
    355   }
    356 
    357   // map matrix
    358   {
    359     assert.deepStrictEqual(
    360       math.map([1, 2, 3], function (value) {
    361         return value * value;
    362       }),
    363       [1, 4, 9]
    364     );
    365   }
    366 
    367   // filter matrix
    368   {
    369     assert.deepStrictEqual(
    370       math.filter([6, -2, -1, 4, 3], function (x) {
    371         return x > 0;
    372       }),
    373       [6, 4, 3]
    374     )
    375     assert.deepStrictEqual(math.filter(['23', 'foo', '100', '55', 'bar'], /[0-9]+/), ["23", "100", "55"]);
    376   }
    377 
    378   // concat matrix
    379   {
    380     assert.deepStrictEqual(math.concat([[0, 1, 2]], [[1, 2, 3]]), [[ 0, 1, 2, 1, 2, 3 ]]);
    381     assert.deepStrictEqual(math.concat([[0, 1, 2]], [[1, 2, 3]], 0), [[ 0, 1, 2 ], [ 1, 2, 3 ]]);
    382   }
    383 
    384   // Matrix is available as a constructor for instanceof checks
    385   {
    386     assert.strictEqual(math.matrix([1, 2, 3]) instanceof math.Matrix, true)
    387   }
    388 }
    389 
    390 /*
    391 Sparse matrices examples
    392 */
    393 {
    394   const math = create(all, {});
    395 
    396   // create a sparse matrix
    397   const a = math.identity(1000, 1000, 'sparse');
    398 
    399   // do operations with a sparse matrix
    400   const b = math.multiply(a, a);
    401   const c = math.multiply(b, math.complex(2, 2));
    402   const d = math.matrix([0, 1]);
    403   const e = math.transpose(d);
    404   const f = math.multiply(e, d);
    405 }
    406 
    407 /*
    408 Units examples
    409 */
    410 {
    411   const math = create(all, {});
    412 
    413   // units can be created by providing a value and unit name, or by providing
    414   // a string with a valued unit.
    415   const a = math.unit(45, 'cm'); // 450 mm
    416   const b = math.unit('0.1m'); // 100 mm
    417   const c = math.unit(b)
    418 
    419   // creating units
    420   math.createUnit('foo');
    421   math.createUnit('furlong', '220 yards');
    422   math.createUnit('furlong', '220 yards', { override: true });
    423   math.createUnit('testunit', { definition: '0.555556 kelvin', offset: 459.67 });
    424   math.createUnit('testunit', { definition: '0.555556 kelvin', offset: 459.67 }, { override: true });
    425   math.createUnit('knot', { definition: '0.514444 m/s', aliases: ['knots', 'kt', 'kts'] });
    426   math.createUnit('knot', { definition: '0.514444 m/s', aliases: ['knots', 'kt', 'kts'] }, { override: true });
    427   math.createUnit(
    428     'knot',
    429     {
    430       definition: '0.514444 m/s',
    431       aliases: ['knots', 'kt', 'kts'],
    432       prefixes: 'long',
    433     },
    434     { override: true }
    435   );
    436   math.createUnit(
    437     {
    438       foo2: {
    439         prefixes: 'long',
    440       },
    441       bar: '40 foo',
    442       baz: {
    443         definition: '1 bar/hour',
    444         prefixes: 'long',
    445       },
    446     },
    447     {
    448       override: true,
    449     }
    450   );
    451   // use Unit as definition
    452   math.createUnit('c', { definition: b });
    453   math.createUnit('c', { definition: b }, { override: true });
    454 
    455   // units can be added, subtracted, and multiplied or divided by numbers and by other units
    456   math.add(a, b);
    457   math.multiply(b, 2);
    458   math.divide(math.unit('1 m'), math.unit('1 s'));
    459   math.pow(math.unit('12 in'), 3);
    460 
    461   // units can be converted to a specific type, or to a number
    462   b.to('cm');
    463   math.to(b, 'inch');
    464   b.toNumber('cm');
    465   math.number(b, 'cm');
    466 
    467   // the expression parser supports units too
    468   math.evaluate('2 inch to cm');
    469 
    470   // units can be converted to SI
    471   math.unit('1 inch').toSI();
    472 
    473   // units can be split into other units
    474   math.unit('1 m').splitUnit(['ft', 'in']);
    475 }
    476 
    477 /*
    478 Expression tree examples
    479 */
    480 {
    481   const math = create(all, {});
    482 
    483   // Filter an expression tree
    484   const node: math.MathNode = math.parse('x^2 + x/4 + 3*y');
    485   const filtered: math.MathNode[] = node.filter((node: math.MathNode) => node.type === 'SymbolNode' && node.name === 'x');
    486 
    487   const arr: string[] = filtered.map((node: math.MathNode) => node.toString());
    488 
    489   // Traverse an expression tree
    490   const node1: math.MathNode = math.parse('3 * x + 2');
    491   node1.traverse((node: math.MathNode, path: string, parent: math.MathNode) => {
    492     switch (node.type) {
    493       case 'OperatorNode':
    494         return node.type === 'OperatorNode';
    495       case 'ConstantNode':
    496         return node.type === 'ConstantNode';
    497       case 'SymbolNode':
    498         return node.type === 'SymbolNode';
    499       default:
    500         return;
    501     }
    502   });
    503 }
    504 
    505 /*
    506 Function floor examples
    507 */
    508 {
    509   const math = create(all, {});
    510 
    511   // number input
    512   assert.strictEqual(math.floor(3.2), 3);
    513   assert.strictEqual(math.floor(-4.2), -5);
    514 
    515   // number input
    516   // roundoff result to 2 decimals
    517   assert.strictEqual(math.floor(3.212, 2), 3.21);
    518   assert.strictEqual(math.floor(-4.212, 2), -4.22);
    519 
    520   // Complex input
    521   const c = math.complex(3.24, -2.71);
    522   assert.deepStrictEqual(math.floor(c), math.complex(3, -3));
    523   assert.deepStrictEqual(math.floor(c, 1), math.complex(3.2, -2.8));
    524 
    525   //array input
    526   assert.deepStrictEqual(math.floor([3.2, 3.8, -4.7]), [3, 3, -5]);
    527   assert.deepStrictEqual(math.floor([3.21, 3.82, -4.71], 1), [3.2, 3.8, -4.8]);
    528 }
    529 
    530 
    531 /*
    532 JSON serialization/deserialization
    533 */
    534 {
    535   const math = create(all, {});
    536 
    537   const data = {
    538     bigNumber: math.bignumber('1.5'),
    539   };
    540   const stringified = JSON.stringify(data);
    541   const parsed = JSON.parse(stringified, math.reviver);
    542   assert.deepStrictEqual(parsed.bigNumber, math.bignumber('1.5'));
    543 }
    544 
    545 /*
    546 Extend functionality with import
    547  */
    548 
    549 declare module 'mathjs' {
    550   interface MathJsStatic {
    551     testFun(): number;
    552     value: number;
    553   }
    554 }
    555 
    556 {
    557   const math = create(all, {});
    558   const testFun = () => 5;
    559 
    560   math.import(
    561     {
    562       testFun,
    563       value: 10,
    564     },
    565     {}
    566   );
    567 
    568   math.testFun();
    569 
    570   const a = math.value * 2;
    571 }
    572 
    573 /*
    574 Renamed functions from v5 => v6
    575  */
    576 {
    577   const math = create(all, {});
    578   math.typeOf(1);
    579   math.variance([1, 2, 3, 4]);
    580   math.evaluate('1 + 2');
    581 
    582   // chained operations
    583   math.chain(3).typeOf().done();
    584   math.chain([1, 2, 3]).variance().done();
    585   math.chain('1 + 2').evaluate().done();
    586 }
    587 
    588 /*
    589 Factory Test
    590  */
    591 {
    592   // create a factory function
    593   const name = 'negativeSquare';
    594   const dependencies: MathJsFunctionName[] = ['multiply', 'unaryMinus'];
    595   const createNegativeSquare = factory(name, dependencies, (injected) => {
    596     const { multiply, unaryMinus } = injected;
    597     return function negativeSquare(x: number): number {
    598       return unaryMinus(multiply(x, x));
    599     };
    600   });
    601 
    602   // create an instance of the function yourself:
    603   const multiply = (a: number, b: number) => a * b;
    604   const unaryMinus = (a: number) => -a;
    605   const negativeSquare = createNegativeSquare({ multiply, unaryMinus });
    606   negativeSquare(3);
    607 }
    608 
    609 /**
    610  * Dependency map typing test from mathjs official document:
    611  * https://mathjs.org/docs/custom_bundling.html#using-just-a-few-functions
    612  */
    613 {
    614   const config = {
    615     // optionally, you can specify configuration
    616   };
    617 
    618   // Create just the functions we need
    619   const { fraction, add, divide, format } = create(
    620     {
    621       fractionDependencies,
    622       addDependencies,
    623       divideDependencies,
    624       formatDependencies,
    625     },
    626     config
    627   );
    628 
    629   // Use the created functions
    630   const a = fraction(1, 3);
    631   const b = fraction(3, 7);
    632   const c = add(a, b);
    633   const d = divide(a, b);
    634   assert.strictEqual(format(c), "16/21");
    635   assert.strictEqual(format(d), "7/9");
    636 }
    637 
    638 /**
    639  * Custom parsing functions
    640  * https://mathjs.org/docs/expressions/customization.html#customize-supported-characters
    641  */
    642 {
    643   const math = create(all, {});
    644   const isAlphaOriginal = math.parse.isAlpha;
    645   math.parse.isAlpha = (c, cPrev, cNext) => {
    646     return isAlphaOriginal(c, cPrev, cNext) || c === "\u260E";
    647   };
    648 
    649   // now we can use the \u260E (phone) character in expressions
    650   const result = math.evaluate("\u260Efoo", { "\u260Efoo": 42 });
    651   assert.strictEqual(result, 42);
    652 }
    653 
    654 /**
    655  * Util functions
    656  * https://mathjs.org/docs/reference/functions.html#utils-functions
    657  */
    658 {
    659   const math = create(all, {});
    660 
    661   // hasNumericValue function
    662   assert.    strictEqual(math.hasNumericValue(2),                    true);
    663   assert.    strictEqual(math.hasNumericValue('2'),                  true);
    664   assert.    strictEqual(math.isNumeric('2'),                        false);
    665   assert.    strictEqual(math.hasNumericValue(0),                    true);
    666   assert.    strictEqual(math.hasNumericValue(math.bignumber(500)),  true);
    667   assert.deepStrictEqual(math.hasNumericValue([2.3, 'foo', false]),  [true, false, true]);
    668   assert.    strictEqual(math.hasNumericValue(math.fraction(4)),     true);
    669   assert.    strictEqual(math.hasNumericValue(math.complex('2-4i')), false);
    670 }
    671 
    672 /**
    673  * src/util/is functions
    674  */
    675 {
    676   const math = create(all, {});
    677 
    678   type IsFunc = (x: unknown) => boolean;
    679   const isFuncs: IsFunc[] = [
    680     math.isNumber,
    681     math.isBigNumber,
    682     math.isComplex,
    683     math.isFraction,
    684     math.isUnit,
    685     math.isString,
    686     math.isArray,
    687     math.isMatrix,
    688     math.isCollection,
    689     math.isDenseMatrix,
    690     math.isSparseMatrix,
    691     math.isRange,
    692     math.isIndex,
    693     math.isBoolean,
    694     math.isResultSet,
    695     math.isHelp,
    696     math.isFunction,
    697     math.isDate,
    698     math.isRegExp,
    699     math.isObject,
    700     math.isNull,
    701     math.isUndefined,
    702     math.isAccessorNode,
    703     math.isArrayNode,
    704     math.isAssignmentNode,
    705     math.isBlockNode,
    706     math.isConditionalNode,
    707     math.isConstantNode,
    708     math.isFunctionAssignmentNode,
    709     math.isFunctionNode,
    710     math.isIndexNode,
    711     math.isNode,
    712     math.isObjectNode,
    713     math.isOperatorNode,
    714     math.isParenthesisNode,
    715     math.isRangeNode,
    716     math.isSymbolNode,
    717     math.isChain
    718   ]
    719 
    720   isFuncs.forEach(f => {
    721     const result = f(1);
    722     const isResultBoolean = result === true || result === false;
    723     assert.ok(isResultBoolean);
    724   })
    725 
    726   // Check guards do type refinement
    727 
    728   let x: unknown
    729 
    730   if (math.isNumber(x)) {
    731     expectTypeOf(x).toMatchTypeOf<number>()
    732   }
    733   if (math.isBigNumber(x)) {
    734     expectTypeOf(x).toMatchTypeOf<math.BigNumber>()
    735   }
    736   if (math.isComplex(x)) {
    737     expectTypeOf(x).toMatchTypeOf<math.Complex>()
    738   }
    739   if (math.isFraction(x)) {
    740     expectTypeOf(x).toMatchTypeOf<math.Fraction>()
    741   }
    742   if (math.isUnit(x)) {
    743     expectTypeOf(x).toMatchTypeOf<math.Unit>()
    744   }
    745   if (math.isString(x)) {
    746     expectTypeOf(x).toMatchTypeOf<string>()
    747   }
    748   if (math.isArray(x)) {
    749     expectTypeOf(x).toMatchTypeOf<unknown[]>()
    750   }
    751   if (math.isMatrix(x)) {
    752     expectTypeOf(x).toMatchTypeOf<math.Matrix>()
    753   }
    754   if (math.isDenseMatrix(x)) {
    755     expectTypeOf(x).toMatchTypeOf<math.Matrix>()
    756   }
    757   if (math.isSparseMatrix(x)) {
    758     expectTypeOf(x).toMatchTypeOf<math.Matrix>()
    759   }
    760   if (math.isIndex(x)) {
    761     expectTypeOf(x).toMatchTypeOf<math.Index>()
    762   }
    763   if (math.isBoolean(x)) {
    764     expectTypeOf(x).toMatchTypeOf<boolean>()
    765   }
    766   if (math.isHelp(x)) {
    767     expectTypeOf(x).toMatchTypeOf<math.Help>()
    768   }
    769   if (math.isDate(x)) {
    770     expectTypeOf(x).toMatchTypeOf<Date>()
    771   }
    772   if (math.isRegExp(x)) {
    773     expectTypeOf(x).toMatchTypeOf<RegExp>()
    774   }
    775   if (math.isNull(x)) {
    776     expectTypeOf(x).toMatchTypeOf<null>()
    777   }
    778   if (math.isUndefined(x)) {
    779     expectTypeOf(x).toMatchTypeOf<undefined>()
    780   }
    781 
    782   if (math.isAccessorNode(x)) {
    783     expectTypeOf(x).toMatchTypeOf<math.AccessorNode>()
    784   }
    785   if (math.isArrayNode(x)) {
    786     expectTypeOf(x).toMatchTypeOf<math.ArrayNode>()
    787   }
    788   if (math.isAssignmentNode(x)) {
    789     expectTypeOf(x).toMatchTypeOf<math.AssignmentNode>()
    790   }
    791   if (math.isBlockNode(x)) {
    792     expectTypeOf(x).toMatchTypeOf<math.BlockNode>()
    793   }
    794   if (math.isConditionalNode(x)) {
    795     expectTypeOf(x).toMatchTypeOf<math.ConditionalNode>()
    796   }
    797   if (math.isConstantNode(x)) {
    798     expectTypeOf(x).toMatchTypeOf<math.ConstantNode>()
    799   }
    800   if (math.isFunctionAssignmentNode(x)) {
    801     expectTypeOf(x).toMatchTypeOf<math.FunctionAssignmentNode>()
    802   }
    803   if (math.isFunctionNode(x)) {
    804     expectTypeOf(x).toMatchTypeOf<math.FunctionNode>()
    805   }
    806   if (math.isIndexNode(x)) {
    807     expectTypeOf(x).toMatchTypeOf<math.IndexNode>()
    808   }
    809   if (math.isNode(x)) {
    810     expectTypeOf(x).toMatchTypeOf<math.MathNodeCommon>()
    811   }
    812   if (math.isNode(x)) {
    813     expectTypeOf(x).toMatchTypeOf<math.MathNodeCommon>()
    814   }
    815   if (math.isObjectNode(x)) {
    816     expectTypeOf(x).toMatchTypeOf<math.ObjectNode>()
    817   }
    818   if (math.isOperatorNode(x)) {
    819     expectTypeOf(x).toMatchTypeOf<math.OperatorNode>()
    820   }
    821   if (math.isParenthesisNode(x)) {
    822     expectTypeOf(x).toMatchTypeOf<math.ParenthesisNode>()
    823   }
    824   if (math.isRangeNode(x)) {
    825     expectTypeOf(x).toMatchTypeOf<math.RangeNode>()
    826   }
    827   if (math.isSymbolNode(x)) {
    828     expectTypeOf(x).toMatchTypeOf<math.SymbolNode>()
    829   }
    830   if (math.isChain(x)) {
    831     expectTypeOf(x).toMatchTypeOf<math.MathJsChain>()
    832   }
    833 }