Type Math.min & Math.max using generic
See original GitHub issueSearch Terms
- Math.min generic
- Math.max generic
Suggestion
Currently, Math.min is typed as:
min(...values: number[]): number;
However, I would like to change the definition to:
min<T extends number>(...values: [T, ...T[]]): T;
min(): number; // Because this will return Infinity
Because Math.min should never return things that aren’t its input. (Except when non-number is passed in, then it’ll return NaN
. But that’s impossible with this typing.)
(Okay, there’s another case: if no value is passed in, it’ll return Infinity
. Unfortunately, there’s no literal type for Infinity
so we can’t type that correctly. ~And AFAIK there’s no way to force at least 1 parameter with rest args.~ Updated: there is, using tuple type: [T, ...T[]]
. Proposal updated. Still, it would be nice to have literal Infinity
type.)
(The same applies with Math.max, except Infinity
is now -Infinity
)
Use Cases
Let’s say I have this type:
type TBankNoteValues = 1 | 5 | 10 | 20 | 50 | 100;
And I want to know what is the highest-value banknote I have in the array. I could use Math.max to find that out. But with the current typing, the return value isn’t guaranteed to be TBankNoteValues.
let values: TBankNoteValues[] = [50, 100, 20];
let maxValues = Math.max(...values); // number
And now I can’t pass maxValues to a function that expects TBankNoteValues anymore.
Examples
type TBankNoteValues = 1 | 5 | 10 | 20 | 50 | 100;
let values: TBankNoteValues[] = [50, 100, 20];
let maxValues = Math.max(...values);
// Current type: number
// Expected type: TBankNoteValues
Checklist
My suggestion meets these guidelines:
- This wouldn’t be a breaking change in existing TypeScript/JavaScript code
Shouldn’t be any. Anything that expects the old signature, TypeScript should just inferT
tonumber
.- Now that I think about it, this make the return type of the function narrows down. So, it could make type inference on a variable declaration changes unexpectedly. An explicit type annotation should fix this.
- This wouldn’t change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript’s Design Goals.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:12
- Comments:8 (2 by maintainers)
Top GitHub Comments
I don’t think annotating the generic as
<T extends number>
is correct becauseT
don’t necessarily have to extendnumber
, it is stated on the language that:Meaning that it could be a
string
as well.Related: #32277