From 09f6da92787891f63ffc8ef03a4befd4bab453db Mon Sep 17 00:00:00 2001 From: mrft <977655+mrft@users.noreply.github.com> Date: Wed, 2 Jul 2025 10:37:44 +0200 Subject: [PATCH] fix: #3493 #3499 #3494 type definitions of `unit(number)`, for `add` and `multiply` without arguments, and for `unit.to(unit)` (#3495) * fixes #3493 allowing math.unit(5), which would now fail because for values of MathNumericType and MathCollection, the second parameter wasn't optional * Added tests, and as a result of that, fixed the definition of unit(value: MathCollection): Unit[] where no units seem to be allowed * Changes as requested by josdejong * math.add and math.multipl type fixes and added tests * fixes #3494: math.unit(m).to(math.unit(cm)) is now ok for typescript --- AUTHORS | 1 + test/typescript-tests/testTypes.ts | 51 ++++++++++++++++++++++++++++++ types/EXPLANATION.md | 2 +- types/index.d.ts | 17 +++++----- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0f270199f..12dcde4d7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -267,5 +267,6 @@ Delaney Sylvans Rani D. <73716554+ranidam@users.noreply.github.com> Don McCurdy Jay Chang <96050090+JayChang4w@users.noreply.github.com> +Frederik Tilkin <977655+mrft@users.noreply.github.com> # Generated by tools/update-authors.js diff --git a/test/typescript-tests/testTypes.ts b/test/typescript-tests/testTypes.ts index c85905b96..c22183e3a 100644 --- a/test/typescript-tests/testTypes.ts +++ b/test/typescript-tests/testTypes.ts @@ -86,8 +86,29 @@ Basic usage examples math.add(math.pow(math.sin(angle), 2), math.pow(math.cos(angle), 2)) math.add(2, 3, 4) math.add(2, 3, math.bignumber(4)) + // @ts-expect-error: string arguments are not supported by the types, but it works (if the string contains a number) + math.add(2, '3') + // @ts-expect-error: string arguments are not supported by the types, but it works (if the string contains a number), but should throw an error if it is something else + assert.throws(() => math.add(2, '3 + 5')) + // @ts-expect-error: string arguments are not supported by the types, but it works (if the string contains a number), but should throw an error if it is something else + assert.throws(() => math.add(2, '3 cm')) + // @ts-expect-error: no arguments are not supported by the types, and should throw an error + assert.throws(() => math.add()) + // @ts-expect-error: 1 argument is not supported by the types, and should throw an error + assert.throws(() => math.add(1)) + math.multiply(2, 3, 4) math.multiply(2, 3, math.bignumber(4)) + // @ts-expect-error: string arguments are not supported by the types, but it works (if the string contains a number) + math.multiply(2, '2') // currently not supported by the types, but turns out to work + // @ts-expect-error: string arguments are not supported by the types, but it works (if the string contains a number), but should throw an error if it is something else + assert.throws(() => math.multiply(2, '3 + 5')) + // @ts-expect-error: string arguments are not supported by the types, but it works (if the string contains a number), but should throw an error if it is something else + assert.throws(() => math.multiply(2, '3 cm')) + // @ts-expect-error: no arguments are not supported by the types, and should throw an error + assert.throws(() => math.multiply()) + // @ts-expect-error: 1 argument is not supported by the types, and should throw an error + assert.throws(() => math.multiply(1)) // std and variance check @@ -1741,6 +1762,35 @@ Units examples { const math = create(all, {}) + /* + Unit function type tests + */ + { + // Test unit function with string argument + expectTypeOf(math.unit('5 cm')).toExtend() + + // Test unit function with Unit argument + expectTypeOf(math.unit(math.unit('5 cm'))).toExtend() + + // Test unit function with MathNumericType and string + expectTypeOf(math.unit(5, 'cm')).toExtend() + expectTypeOf(math.unit(math.bignumber(5), 'cm')).toExtend() + expectTypeOf(math.unit(math.fraction(5, 2), 'cm')).toExtend() + expectTypeOf(math.unit(math.complex(5, 0), 'cm')).toExtend() + + // Test unit function with just MathNumericType (optional unit parameter) + expectTypeOf(math.unit(5)).toExtend() + expectTypeOf(math.unit(math.bignumber(5))).toExtend() + expectTypeOf(math.unit(math.fraction(5, 2))).toExtend() + // Shouldn't this also work? Currently it does not. + // expectTypeOf(math.unit(math.complex(5, 0))).toExtend() + + // Test unit function with just MathCollection + expectTypeOf(math.unit(math.matrix([1, 2, 3]))).toExtend() + expectTypeOf(math.unit([1, 2, 3])).toExtend() + expectTypeOf(math.unit(math.matrix(['2cm', '5cm']))).toExtend() + } + // units can be created by providing a value and unit name, or by providing // a string with a valued unit. const a = math.unit(45, 'cm') // 450 mm @@ -1803,6 +1853,7 @@ Units examples // units can be converted to a specific type, or to a number b.to('cm') + b.to(math.unit('m')) math.to(b, 'inch') b.toNumber('cm') math.number(b, 'cm') diff --git a/types/EXPLANATION.md b/types/EXPLANATION.md index 8f83778aa..c58edb2bb 100644 --- a/types/EXPLANATION.md +++ b/types/EXPLANATION.md @@ -20,7 +20,7 @@ Maintaining the TypeScript types is done manually. When adding a function, one h 3. Add a static definition inside `export const {...} : MathJsInstance` 4. Add a dependencies definition inside `export const {...} : Record` -For exampe for the function `add`, we can have the following definitions: +For example for the function `add`, we can have the following definitions: ```ts // instance diff --git a/types/index.d.ts b/types/index.d.ts index 9c43dc712..ed3b15892 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -867,8 +867,8 @@ export interface MathJsInstance extends MathJsFactory { * @param unit The unit to be created * @returns The created unit */ - unit(value: MathNumericType, unit: string): Unit - unit(value: MathCollection, unit: string): Unit[] + unit(value: MathNumericType, unit?: string): Unit + unit(value: MathCollection): Unit[] /************************************************************************* * Expression functions @@ -1136,9 +1136,9 @@ export interface MathJsInstance extends MathJsFactory { * @returns Sum of x and y */ add(x: T, y: T): T - add(...values: T[]): T + add(x: T, y: T, ...values: T[]): T add(x: MathType, y: MathType): MathType - add(...values: MathType[]): MathType + add(x: MathType, y: MathType, ...values: MathType[]): MathType /** * Calculate the cubic root of a value. @@ -1465,9 +1465,8 @@ export interface MathJsInstance extends MathJsFactory { multiply(x: T, y: T): MathScalarType multiply(x: Unit, y: Unit): Unit multiply(x: number, y: number): number - multiply(x: MathType, y: MathType): MathType - multiply(...values: T[]): T - multiply(...values: MathType[]): MathType + multiply(x: MathType, y: MathType, ...values: MathType[]): MathType + multiply(x: T, y: T, ...values: T[]): T /** * Calculate the norm of a number, vector or matrix. The second @@ -4177,7 +4176,7 @@ export interface Unit { divide(unit: Unit): Unit | number pow(unit: Unit): Unit abs(unit: Unit): Unit - to(unit: string): Unit + to(unit: string | Unit): Unit toNumber(unit?: string): number toNumeric(unit?: string): number | Fraction | BigNumber toSI(): Unit @@ -4827,7 +4826,7 @@ export interface MathJsChain { */ unit(this: MathJsChain, unit?: string): MathJsChain unit(this: MathJsChain, unit?: string): MathJsChain - unit(this: MathJsChain, unit?: string): MathJsChain + unit(this: MathJsChain): MathJsChain /************************************************************************* * Expression functions