New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
isNaN shouldn't be considered a number #1406
Comments
It's hard to track when operations might return |
I think numbers should stay as they are, but it would be nice to have a separate type for finite numbers (no Then we can define signatures of operators as following: + : (number, number) => number
+ : (number, finite_number) => number
+ : (finite_number, number) => number
+ : (finite_number, finite_number) => finite_number
/ : (finite_number, finite_number) => number
etc |
plot twist: you'd agree
|
I would strongly support to add the type To get away from the headache how exactly it should behave, I suggest to use Lodash It has been there for ages for a good reason, even before Lodash existed, as one of the core utilities from Underscore, and Lodash still defers to it: https://github.com/lodash/lodash/blob/master/vendor/underscore/underscore.js#L1311-L1314 // Is a given object a finite number?
_.isFinite = function(obj) {
return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj));
}; Note it does not use the native What we likely don't want is this: isFinite('1') // true Which also caused people some headaches: The signature is affected by several constants incl. However, the resulting type depends on the value (instead of only type): Number.isFinite(Number.MAX_VALUE + 1) // true, because of the rounding
Number.isFinite(Number.MAX_VALUE + Number.MAX_VALUE) // false So what can we do?
The reasoning: If you have any of those inside your code, you are at clear risk of getting infinities. So the mere reason you put type And perhaps, to avoid questions like "why is that not of type |
Just to attempt some clarification. As a professional mathematician, I would like to have a proper mathematical type for real numbers. That would be clean and intuitive to anyone not familiar with implementation details. The basic idea is simple. Mathematics clearly defines what real numbers are and what operations are permitted. Entities like
is not mathematically distinguishable from 0. Therefore, it must be treated as 0 for real-number typechecking purposes. In other words, only mathematically unambiguous real numbers can be whitelisted. Only for them, algebra rules guarantee operational safety. All other entities may lead to potential bugs. As example, this function should be considered safe: function safeSquare (x: finite): finite {
return x * x
} The fact that it might get evaluated to But here is the real problem -- what if another programmer puts this number somewhere in the code for presumably "legitimate" purposes. Or your dependency third party library has it somewhere down the code. Then, if there is any risk, I want to be warned! Here is a concrete example of unsafe function where I want to be warned: function unsafeDivide (x: finite, y: finite): finite {
return x / y
} Here there is a clear risk that function safeDivide (x: finite, y: nonzero): finite {
return x / y
} So I need the type The type
For instance, the above function Note that this guarantee philosophy is orthogonal to JavaScript's don't fail at any cost. The latter tells you that Yes, it makes a perfect business sense to keep your app running suppressing all those errors that might be of no relevance to the user. Or the user will be presented with the payment bill of And in 98% cases, it is probably ok to move on, and the user won't even notice. In contrast, the guarantee principle will give you as programmer a complete peace of mind, because it will warn you about any conceivable potential violation. It should not be a human task to write all imaginable unit tests to safeguard against all possible imaginable and non-imaginable troubles. Not even mention, many teams don't even bother writing tests at all or write only minimum possible. The right "person" to deal with this problem is the compiler! |
This is not enough, any expression involving should not evaluate to
I think it's impossible to use javascript numbers for this. |
Exactly what I tried to say by "NOT of type finite":
What are the problems? |
I meant to say, any expression involving finite. There is nothing special about Number.MAX_VALUE, you can get it by adding two finite numbers
For starters, real numbers are an infinite set, javascript numbers are a finite set |
Adding two of those numbers will give you
How is this a problem for my proposal? |
Not true,
It's not a problem with your proposal, it's a problem with 'proper mathematical type for real numbers' idea |
This behavior is part of the spec and is not implementation-dependent: Unfortunately I don't think this is something that Flow will be able to prove. |
One of the reasons I've chosen Flowtype is to get rid of
NaN
crazyness in my team's code.I expect functions not to return
NaN
if I annotate them to returnnumber
.IMHO this should not be valid. Any reason why we should care this JS legacy in Flow?
Cheers
The text was updated successfully, but these errors were encountered: