2016-05-17 32 views
3

The built-in type number in Flow允许“异国情调”的值,如Infinity,-InfinityNaN如何声明不包含无穷和NaN的数字的流类型?

我该如何强制类型只允许实数?

编辑。 这是不是一个问题如何检查一个变量是否是实数。 这是关于使用Flow打字。

我正在寻找的方式来写我的功能,如:

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

我的问题是如何界定real所以它的工作原理与流程(http://flowtype.org/)类型。

+0

用户正则表达式'[0-9] +'。你也可以使用'typeof'或'isNaN()' – vaso123

+0

@lolka_bolka你能提供一个正则表达式的例子吗? (我宁愿不依赖于已知是越野车的原生类型。) –

+0

也许这是http://stackoverflow.com/questions/4724555/how-do-i-check-if-a-number-evaluates-to -infinity – maioman

回答

2

你不能这样做使用流量。你需要运行时检查。

看到实数这里的问题进行了讨论:https://github.com/facebook/flow/issues/1406

底线是,相当多的实数的任何操作可能会导致无穷,实数,并且NaN之间,区分/无限远不会是非常有用的因为它会返回一个类型,而不是保证是真实的。

例如,

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 

分别从讨论中,流量不必黑名单一定值的任何设施,同时允许其他同类型的值。您只能使用白名单值,包括使用联合和交叉点。

+1

谢谢,请参阅更新的建议:https://github.com/facebook/flow/issues/1406#issuecomment-219905558 –

+0

基本上建议使用白名单。您的任何示例都不会列入白名单(请参阅问题)。 –

+0

在你的github评论的上下文中:如果我有数字“a:非零”和“b:非零”,那么例如'a + b'将是'finite'类型,而不是'nonzero',因为Flow的类型系统可以从来没有证明。因此,在实践中,您需要在运行时检查0以将这些操作的结果细化为“非零”,类似于我们如何检查null以将可空类型细化为非可空类型。请注意,如果没有特殊的“非零”类型,这也会起作用。 – Nikita

0

有一点中间地带,你可以用这个与流罢工。是的,您需要使用运行时检查来最终解决这个问题,但是您可以构建一个不透明的类型,以使Flow强制您不能绕过这些验证函数。首先,在一个文件中,把这个:

// @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; 

// 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; 
} 

然后,使用那些像这样:

// @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 become isPrime(3) 
isPrime(3.14);  // Flow error! 
相关问题