[ React, TypeScript ] URL クエリパラメータ文字列が数字かどうかを判定する
動機
https://example.com?hoge=12345
のような URL を運用したいときに hoge の値が数字になっているかどうかを確かめたい
hoge の内容は react-router の query で取得でき、その型は string | string[] | undefined
となっている。なので見た目は数字でも型は文字列ということだ
それから string[]
と、配列になっている場合があるが、これは
?hoge=12345&hoge=67890
のように & で hoge をつなげると ["12345", "67890"]
として取得できる
今回はこういった hoge の値に数字ではなく abc のような文字が含まれていないようにしたい
厳密には正規表現などで判定するべきなのだが簡単に対応したい
そういった要件をみたしつつやるとするならば以下のようにやる
isNaN もしくは isFinite を使う
見た目が数字の文字列が本当に数字かどうか判定するのに手軽な方法
こちらを参考
isNaN は非数の場合に true を返し isFinite は数字 ( 有限数 ) の場合に true を返す。これらの真偽判定は大概真逆になっていると考えて差し支えない
本来ならより堅牢な Number.isNaN
や Number.isFinite
を使うべきなのだろうが TypeScript では isNaN や isFinite の引数に文字列を指定しようとすると number でないと怒られるのでどのみち isNaN(Number(hoge))
などとしてやる必要がある
考えられるクエリパラメータで真偽判定がどうなるかを検証。 isNaN で確かめてみる
isNaN(Number(hoge))
// 1 ...?hoge=12345 => false ( 数字である )
// 2 ...?hoge=12345abc => true ( 数字でない )
// 3 ...?hoge=12345&hoge=67890 => true ( 数字でない )
// 4 ...?hoge=12345abc&hoge=67890def => true ( 数字でない )
実際 Number(hoge)
としている時点で hoge 数字以外の文字が含まれている場合この値は NaN になっているのでそういうものについては isNaN(NaN) を確かめていいるにすぎない
string[]
となる場合 (3, 4) については厳密には配列かどうかの判定をしてそれぞれについて数字かどうかをチェックしなければいけないが今回は省略
3 や 4 を Number(hoge)
すると NaN となるがどんな文字列が NaN となっているのかを確かめるために一度 String(hoge)
としてみると
"12345,67890" // 3 の場合
となっていることがわかる。これを無理やり数値化しようとすると「 , 」 が入っているので NaN となる
補足
参考のリンクでも言及されているが null
や false
、 true
は数値に変換すると 0 や 1 になるため isNaN をかますと false ( つまり数字ですよ〜 ) となる。これは正しい挙動だが今回の要件からするとそうなってほしくない
ただ状況がクエリパラメータなので null や false は文字列として入ってくる。 Number('null')
は NaN になるので判定に影響はでないと考える
本当は 0x12 や小数や負数や BigInt やらも弾きたいのだがそうなってくると沼にはまりそうなので今回は abc のような文字が含まれていなければクリアということにしている
Discussion