2016-05-17 1 views
3

The built-in type number in Flow ermöglicht die "exotischen" Werte wie Infinity, -Infinity und NaN.Wie wird der Flow-Typ für Zahlen deklariert, die Unendlichkeiten und NaN ausschließen?

Wie kann ich den Typ erzwingen, um nur reelle Zahlen zuzulassen?

BEARBEITEN. Dies ist nicht eine Frage, wie Sie überprüfen, ob eine Variable reelle Zahl ist. Es geht darum, mit Flow zu tippen.

Ich suche die Art und Weise meine Funktionen zu schreiben wie:

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

Meine Frage ist, wie die Art zu definieren real so dass es mit Flow Works (http://flowtype.org/).

+0

Benutzer einen regulären Ausdruck '[0-9] +'. Sie können auch 'typeof' oder' isNaN() ' – vaso123

+0

@lolka_bolka verwenden. Können Sie ein Beispiel mit dem regulären Ausdruck angeben? (Ich würde mich lieber nicht auf native typeof verlassen, von der bekannt ist, dass sie fehlerhaft ist.) –

+0

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

Antwort

2

Mit Flow können Sie das nicht tun. Sie benötigen Laufzeitprüfungen.

Siehe Diskussion der Themen, mit reellen Zahlen hier: https://github.com/facebook/flow/issues/1406

Unterm Strich ist, so ziemlich jede Operation auf reelle Zahlen in der Unendlichkeit führen könnte, so zwischen reellen Zahlen und NaN Unterscheidung/Unendlich wäre nicht sehr sinnvoll sein, da es einen Typ zurückgeben würde, der nicht wirklich echt ist.

Zum Beispiel

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 

Getrennt von dieser Diskussion, Fluss hat keine Einrichtungen zu schwarzen Liste bestimmte Werten, während andere Werte des gleichen Typs zu ermöglichen. Sie können nur Whitelist Werte, einschließlich der Verwendung von Gewerkschaften und Kreuzungen.

+1

Danke, siehe das Angebot aktualisiert: https://github.com/facebook/flow/issues/1406#issuecomment-219905558 –

+0

Grundsätzlich wird ein Whitelisting vorgeschlagen. Keines Ihrer Beispiele würde auf die weiße Liste gesetzt (siehe Problem). –

+0

Im Zusammenhang mit Ihrem GitHub-Kommentar: Wenn ich die Zahlen 'a: ungleich Null 'und' b: ungleich Null' habe, dann wäre zum Beispiel 'a + b' vom Typ 'endlich', nicht 'ungleich Null', weil das Fließkomma-System es könnte Beweisen Sie nie etwas anderes.In der Praxis müssten Sie also zur Laufzeit auf 0 überprüfen, um das Ergebnis solcher Operationen auf "ungleich Null" zu beschränken, ähnlich wie wir nach "null" suchen, um Nullwert-Typen in Nicht-Nullable-Typen zu verfeinern. Beachten Sie, dass dies auch ohne einen speziellen 'Nullen'-Typ funktioniert. – Nikita

0

Es gibt ein bisschen mittleren Boden, den Sie damit mit Flow schlagen können. Ja, Sie müssen am Ende eine Laufzeitprüfung durchführen, aber Sie können einen undurchsichtigen Typ erstellen, mit dem Flow erzwingen kann, dass Sie diese Validierungsfunktionen nicht umgehen können. Zuerst wird in einer Datei, diese setzen:

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

Dann verwenden Sie die wie 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 become isPrime(3) 
isPrime(3.14);  // Flow error! 
Verwandte Themen