javascript - How to declare the Flow type for numbers that excludes infinities and NaN? - Stack Overflow

The built-in type number in Flow allows the "exotic" values such as Infinity, -Infinity and N

The built-in type number in Flow allows the "exotic" values such as Infinity, -Infinity and NaN.

How can I enforce the type to only allow real numbers?

EDIT. This is not a question how to check if a variable is real number. It is about typing with Flow.

I am looking for the way to write my functions like:

// @flow
function sum (x: real, y: real) { ... }

My question is how to define the type real so it works with Flow (/).

The built-in type number in Flow allows the "exotic" values such as Infinity, -Infinity and NaN.

How can I enforce the type to only allow real numbers?

EDIT. This is not a question how to check if a variable is real number. It is about typing with Flow.

I am looking for the way to write my functions like:

// @flow
function sum (x: real, y: real) { ... }

My question is how to define the type real so it works with Flow (http://flowtype/).

Share Improve this question edited May 17, 2016 at 8:14 Dmitri Zaitsev asked May 17, 2016 at 8:00 Dmitri ZaitsevDmitri Zaitsev 14.1k12 gold badges78 silver badges114 bronze badges 7
  • user a regular expression [0-9]+. You can also use typeof or isNaN() – vaso123 Commented May 17, 2016 at 8:03
  • @lolka_bolka Can you provide an example with the regular expression? (I'd rather not rely on native typeof that is known to be buggy.) – Dmitri Zaitsev Commented May 17, 2016 at 8:06
  • maybe this stackoverflow./questions/4724555/… – maioman Commented May 17, 2016 at 8:08
  • @AliMamedov StackOverflow langauge is english. Plese use english. Thx, – vaso123 Commented May 17, 2016 at 8:09
  • if (value.match(/^[0-9]+$/)) {} where value is variable what contain the number what you want to validate. But this is only for integers. Here is another, waht can handle sign and floats too: [-+]?[0-9]*\.?[0-9]* – vaso123 Commented May 17, 2016 at 8:10
 |  Show 2 more ments

2 Answers 2

Reset to default 4

You can't do that using Flow. You'll need runtime checks.

See discussion of the issues with real numbers here: https://github./facebook/flow/issues/1406

The bottom line is, pretty much any operation on real numbers could result in infinity, so distinguishing between real numbers and NaN / Infinity would not be very useful as it would return a type than is not guaranteed to be real.

For example,

Number.MAX_VALUE + Number.MAX_VALUE === Infinity
-Number.MAX_VALUE - Number.MAX_VALUE === -Infinity
Number.MAX_VALUE * 2 === Infinity
Number.MAX_VALUE / 0.5 === Infinity

Separately from that discussion, Flow doesn't have any facilities to blacklist certain values while allowing other values of the same type. You can only whitelist values, including using unions and intersections.

There is a bit of middle ground you can strike with this with Flow. Yes, you'll need to use a runtime check to pull this off in the end, but you can construct an opaque type that will let Flow enforce you cannot bypass those validation functions. First, in one file, put this:

// @flow

// Define `Int` as an opaque type.  Internally, it's just a number.
// It's opaque because only this module can produce values of
// this kind, so in order to obtain an "Int", one _must_ use one of
// these functions, which (at runtime) will guarantee that these
// will always be integers.
export opaque type Int: number = number;

// Here's a function that will convert any number to an Int by running
// a typecheck at runtime and perhaps change the value (by rounding)
// This is the ONLY way of obtaining a value of the type Int   
export function int(n: number): Int {
    if (!Number.isFinite(n)) {
        throw new Error('Not a (finite) number');
    }

    // Round any real numbers to their nearest int
    return Math.round(n);
}

// In your private functions, you can now require Int inputs
export function isPrime(n: Int): boolean {
    // In here, you can assume the value of `n` is guaranteed to be an Integer number
    for (let i = 2; i < Math.sqrt(n); i++) {
        if (n % i === 0) return false;
    }
    return true;
}

Then, you use those like so:

// @flow

import { int, isPrime } from './lib';

isPrime(int(NaN));   // ok, but a runtime error, because NaN is not a number!
isPrime(int(3.14));  // ok, will effectively bee isPrime(3)
isPrime(3.14);       // Flow error!

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744886744a4599165.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信