mathjs icon indicating copy to clipboard operation
mathjs copied to clipboard

aggregation operations on 2d arrays using axis 1 don't return an array type and return only MathScalarType

Open jeffzyliu opened this issue 1 year ago • 3 comments

Describe the bug On functions like mean, min, max, std, if you take some 2d number array and want to aggregate it along the 1 axis to retrieve a 1d array of output, you want to get some kind of array/matrix/vector type back. However, it only returns MathScalarType which causes a typescript error. I believe that this code in the types/index.d.ts file at line 2668 causes this:

  /**
   * @param A A single matrix
   * @param dimension The mean over the selected dimension
   * @returns The mean value
   */
  mean<T extends MathScalarType>(
    A: T[] | T[][],
    dimension?: number | BigNumber
  ): T

This has a return value of T, but it actually returns T[] when you have dimension=1 and we want the annotated type to match.

To Reproduce something like

const dataArray: number[][] = [[1, 2], [3, 4]];
const resultArray: number[] = math.mean(dataArray, 1);

should create an error saying "Type 'MathScalarType' is not assignable to type 'number[]'". But this works perfectly as intended and does actually return the answer correctly.

This happens on mean, min, max, std, and maybe more things that involve axis but I haven't tested them.

jeffzyliu avatar Feb 19 '24 07:02 jeffzyliu

Thanks for reporting. Anyone able to help improve these type definitions?

josdejong avatar Feb 21 '24 10:02 josdejong

I wanted to take this up but @josdejong didn't get exact issue, can you help me here ?

rakheesingh avatar Feb 22 '24 16:02 rakheesingh

Thanks @rakheesingh .

To solve this issue, we need to go through all statistical functions like mean that have an optional property dimension, and change the type definition such that it matches the actual behavior. When dimension is provided, the returned type will not be a scalar but a matrix/array (just try it out to see what happens :) ).

For example:

const A = [[1, 2], [3, 4]]
math.mean(A)                 // number 2.5
math.mean(A, 1)              // Array  [ 1.5, 3.5 ]
math.mean(math.matrix(A), 1) // Matrix [ 1.5, 3.5 ]

Some pointers:

  • source code of the statistical functions: https://github.com/josdejong/mathjs/tree/develop/src/function/statistics
  • type definitions: https://github.com/josdejong/mathjs/blob/develop/types/index.d.ts
  • tests of the type definitions https://github.com/josdejong/mathjs/blob/develop/test/typescript-tests/testTypes.ts

josdejong avatar Feb 23 '24 11:02 josdejong