W Typescript, jak sprawdzić, czy ciąg jest numeryczny


184

W programie Typescript wyświetla się błąd mówiący, że isNaN akceptuje tylko wartości liczbowe

isNaN('9BX46B6A')

a to zwraca wartość false, ponieważ parseFloat('9BX46B6A')wartościuje do9

isNaN(parseFloat('9BX46B6A'))

Nadal mogę działać z błędem wyświetlanym w Visual Studio, ale chciałbym to zrobić we właściwy sposób.

Obecnie napisałem tę zmodyfikowaną funkcję -

static isNaNModified = (inputStr: string) => {
    var numericRepr = parseFloat(inputStr);
    return isNaN(numericRepr) || numericRepr.toString().length != inputStr.length;
}

Odpowiedzi:


338

Sposobem na przekonwertowanie ciągu znaków na liczbę jest użycie Number, a nie parseFloat.

Number('1234') // 1234
Number('9BX9') // NaN

Możesz także użyć jednoargumentowego operatora plus, jeśli lubisz skrót:

+'1234' // 1234
+'9BX9' // NaN

Zachowaj ostrożność podczas sprawdzania względem NaN (operator ===i !==nie działaj zgodnie z oczekiwaniami NaN). Posługiwać się:

 isNaN(maybeNumber) // returns true if NaN, otherwise false

18
czy to oznacza, że ​​robienie tego: if (isNaN (+ possibleNumberString)) jest prawidłowym sposobem sprawdzenia?
Mathijs Segers

5
Dlaczego miałbyś używać Numberpowyższego parseIntlub parseFloat? Number('')daje 0, a parseInt('')daje, NaNco jest bardziej zgodne z tym, czego oczekuję.
Didii,

6
Jak wspomniano w pierwotnym pytaniu , parseInt('9BX9')(i parseFloat('9BX9')) wróci 9, nie NaN. Jeśli nie chcesz konwersji pustego ciągu na 0, najpierw sprawdź jawnie pusty ciąg.
C Snover

1
Jeśli chcesz to sprawdzić, użyj isNaN(Number(what_ever))zamiast Number(what_ever) === Nan.
k0pernikus

3
@sauntimo Numbernie jest elementem TypeScript, jest to wbudowana funkcja konstruktora EcmaScript, która przyjmuje wartość i zwraca liczbę pierwotną, gdy jest wywoływana jako funkcja, a nie konstruktor.
C Snover

46

Zaktualizuj 2

Ta metoda nie jest już dostępna w rxjs v6

Mam rozwiązać go za pomocą IsNumeric operator rxjs biblioteki (importowanie rxjs / util / IsNumeric

Aktualizacja

import { isNumeric } from 'rxjs/util/isNumeric';

. . .

var val = "5700";
if (isNumeric(val)){
   alert("it is number !");
}

5
Ta metoda nie jest już dostępna w rxjs v6.
Logic01

35
function isNumber(value: string | number): boolean
{
   return ((value != null) &&
           (value !== '') &&
           !isNaN(Number(value.toString())));
}


3

Wybrałbym istniejące i sprawdzone już rozwiązanie. Na przykład to z rxjs w maszynie:

function isNumeric(val: any): val is number | string {
  // parseFloat NaNs numeric-cast false positives (null|true|false|"")
  // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  // subtraction forces infinities to NaN
  // adding 1 corrects loss of precision from parseFloat (#15100)
  return !isArray(val) && (val - parseFloat(val) + 1) >= 0;
}

rxjs / isNumeric.ts

Bez funkcji rxjs isArray () iz prostymi typami:

function isNumeric(val: any): boolean {
  return !(val instanceof Array) && (val - parseFloat(val) + 1) >= 0;
}

Zawsze powinieneś testować takie funkcje w swoich przypadkach użycia. Jeśli masz specjalne typy wartości, ta funkcja może nie być Twoim rozwiązaniem. Możesz przetestować tę funkcję tutaj.

Wyniki są następujące:

enum         : CardTypes.Debit   : true
decimal      : 10                : true
hexaDecimal  : 0xf10b            : true
binary       : 0b110100          : true
octal        : 0o410             : true
stringNumber : '10'              : true

string       : 'Hello'           : false
undefined    : undefined         : false
null         : null              : false
function     : () => {}          : false
array        : [80, 85, 75]      : false
turple       : ['Kunal', 2018]   : false
object       : {}                : false

Jak widać, musisz uważać, jeśli używasz tej funkcji z wyliczeniami.


1

W większości przypadków wartością, którą chcemy sprawdzić, jest ciąg lub liczba, więc oto funkcja, której używam:

const isNumber = (n: string | number): boolean => 
    !isNaN(parseFloat(String(n))) && isFinite(Number(n));

Testy Codesandbox .

const willBeTrue = [0.1, '1', '-1', 1, -1, 0, -0, '0', "-0", 2e2, 1e23, 1.1, -0.1, '0.1', '2e2', '1e23', '-0.1', ' 898', '080']

const willBeFalse = ['9BX46B6A', "+''", '', '-0,1', [], '123a', 'a', 'NaN', 1e10000, undefined, null, NaN, Infinity, () => {}]

1

Możesz użyć Number.isFinite()funkcji:

Number.isFinite(Infinity);  // false
Number.isFinite(NaN);       // false
Number.isFinite(-Infinity); // false
Number.isFinite('0');       // false
Number.isFinite(null);      // false

Number.isFinite(0);         // true
Number.isFinite(2e64);      // true

Uwaga: istnieje znacząca różnica między funkcją globalną isFinite()a drugą Number.isFinite(). W przypadku pierwszego z nich wykonywany jest wymuszenie strun - czyli isFinite('0') === truepodczas gdy Number.isFinite('0') === false.

Pamiętaj też, że nie jest to dostępne w IE!


Ale ... TS2345: Argumentu typu „1” nie można przypisać do parametru typu „numer”. Musi to być Number.isFinite (Number ('0'));
Mcgri

0

Dla pełnych liczb (nie zmiennoprzecinkowych) w Angular możesz użyć:

if (Number.isInteger(yourVariable)) { ... }


1
Number.isIntegerpo prostu mówi ci, czy yourVariable, który jest już numbertypem, jest liczbą całkowitą. Nie działa ze sznurkami. Więc Number.isInteger(Number(yourVariable))może załatwić sprawę.
tarrball

-2

To, czy ciąg może być analizowany jako liczba, jest problemem w czasie wykonywania. Typescript nie obsługuje tego przypadku użycia, ponieważ koncentruje się na bezpieczeństwie czasu kompilacji (nie w czasie wykonywania).


11
Wystarczy oznaczyć to jako błąd, jakby sugerować, że nie jest poprawny.
Jane Panda,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.