JavaScript データ型チェックチートシート - DEV コミュニティ

JavaScript (JS) は軽量で、インタープリタ型またはジャストインタイムコンパイル型のプログラミング言語です。ファーストクラス関数としての機能があります。

MDN Web Docs - JavaScript

この投稿では、一般的な JavaScript データ型チェック、落とし穴、特有の解決策を詳細に解説します。

クラシック JavaScript データ型チェック

以下は、JavaScript での最も一般的なデータ型チェックのコレクションです。変数が Date や Promise、ただの旧式の JavaScript オブジェクトや配列を含んでいるかをチェックしたい場合は、ここに全てあります。

プリミティブ型から number、boolean、string の検出、関数の検出まで全て。

JavaScript の変数がオブジェクトを含んでいるかをチェックする

typeof はオブジェクトに対して 'object' を出力します。

これは null と配列に対しても同様です。

const object = {};

console.log(typeof object); // 'object'
console.log(typeof null); // 'object'
console.log(typeof []); // 'object'

console.log(object instanceof Object); // true
console.log(null instanceof Object); // false
console.log([] instanceof Object); // true

さらに、配列の場合と同じように、フレーム間の通信があり、オブジェクトと配列を共有する傾向があるため(JavaScript 配列型チェック - 「is array」対オブジェクト深掘り を参照)、単純なオブジェクトとクラスのインスタンスを区別するのは難しいです。

JavaScript では全てがオブジェクトなので、存在しないプロパティにアクセスしようとすると静かに失敗します(つまり undefined を返します):

console.log('aaaaa'.noProperty); // undefined
console.log([].nothing); // undefined

慣用的な JavaScript コードでは、例えば growl メソッドを持つオブジェクトが期待されますが、他のものが渡されるかもしれません:

function safeGrowl(anything) {
  if (anything.growl) {
    anything.growl()
  }
}

safeGrowl('hello'); // 何もしない
safeGrowl({ growl() { console.log('Growl!') }}); // Growl!

教訓は、何かがオブジェクトであるかどうかをチェックしないことです。必要なプロパティがあるかどうかをチェックしてください(これを「ダックタイピング」と呼びます)。

値が JavaScript の文字列かどうかをチェックする

文字列については typeof チェックを使用できます。

オブジェクトチェックと同じように、JavaScript は文字列ではないものを文字列として使おうとするときに、大声で失敗することはず、通常はそれを強制的に変換したり、.toString を呼び出したりします。

const string = 'Hello World';
console.log(typeof string); // 'string'

// テンプレートを使用した文字列への暗黙の強制変換
const helloCount = 2;
const newString = `Hello number ${helloCount} at ${new Date('2019-06-23T21:00:26.861Z')}`;

console.log(newString);
// 'Hello number 2 at Sun Jun 23 2019 22:00:26 GMT+0100 (British Summer Time)'

これは日付や数字にも機能します。直接 toString メソッドを実装していない配列や他のオブジェクトの場合は、JSON.stringify を使用することをお勧めします。

const myArray = ['a', 'b', 'c'];
const mySimpleObject = { key: 'value' };

console.log(`${myArray} ${mySimpleObject}`); // 'a,b,c [object Object]'
console.log(`${JSON.stringify(myArray)} ${JSON.stringify(mySimpleObject)}`)
// '["a","b","c"] {"key":"value"}'

値が JavaScript の Number/Integer (数字/整数) かどうかをチェックする

JavaScript の Number は楽しさの宝庫です。object チェックと同様に、NaN(Non a Number)値というゴッチャがあります。NaN は、オペランドの一つが Number でない場合に算術を試みた結果です。

NaN の奇妙な点は自分自身と等しくないことと、実際には Infinity- Infinity と同じように Number であることです。

console.log(NaN == NaN); // false
console.log(NaN === NaN); // false

console.log(typeof NaN); // 'number'
console.log(typeof Infinity); // 'number'
console.log(typeof -Infinity); // 'number'
console.log(typeof 123); // 'number'

Number が NaN でないことをチェックする

NaN の一つのチェック方法は次のとおりです:

const a = NaN;

function isNotANumber(maybeNotANumber) {
  return maybeNotANumber === maybeNotANumber;
}

isNotANumber(a); // true

お勧めのアプローチは、組み込みの Number.isNaN 関数を使用することです:

console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN('abc')); // false
console.log(Number.isNaN(1234)); // false
console.log(Number.isNaN(123.11)); // false
console.log(Number.isNaN(true)); // false

Number.isNaN とグローバル isNaN の違いは、Number.isNaN は渡された値が Number で_かつ_ NaN であることをチェックします。

古いグローバル isNaN 関数は、単に何かが数字ではないことを文字通りにチェックします。

console.log(isNaN(NaN)); // true
console.log(isNaN('abc')); // true
console.log(isNaN(1234)); // false
console.log(isNaN(123.11)); // false
console.log(isNaN(true)); // false

JavaScript の変数が整数を含んでいるかをチェックする

JavaScript の変数(または値)が整数であるかをチェックするには Number.isInteger を使用できます:

console.log(Number.isInteger(123)); // true
console.log(Number.isInteger(12.3)); // false
console.log(Number.isInteger(123.0)); // true

JavaScript の変数が使える Number 値を含んでいるかをチェックする

使える入力値を持っているかをチェックするには、その型が number であり、値が NaN でないことを確認します:

function isValidNumber(maybeNumber) {
  return typeof maybeNumber === 'number' && !Number.isNaN(maybeNumber);
}

console.log(isValidNumber('aaaaa')); // false
console.log(isValidNumber(NaN)); // false
console.log(isValidNumber(123)); // true
console.log(isValidNumber(1.23)); // true

値が boolean であるかどうかをチェックする

JavaScript の文字列や数値型のように、JavaScript では何かが boolean であると仮定する(または boolean にキャストする)パターンがあります。それは JavaScript のゆるい型付けのため、論理演算子を boolean 以外の値と共に使用できるからです。これは通常、「真偽性」と「偽性」の概念を通じて説明されます。

JavaScript が boolean を求められ、下記の値のいずれかが与えられた場合、常に「偽」に評価されます。

MDN Web Docs - Falsy

問題の値(偽とされる値)は次のとおりです:false0''(またはその他の空文字列)、nullundefined。他の値は全て真と評価されます。

undefined の場合とは異なる何かが false を意味する場合には、typeof を使用することによって、値が偽である_かつ_ boolean であるとチェックすることができます:

console.log(typeof true); // 'boolean'
console.log(typeof false); // 'boolean'

変数が配列を含んでいるかをチェックする

JavaScript の変数が配列かどうかをチェックするには、組み込みの Array.isArray があります。

JavaScript 配列の楽しいゴッチャは、それらが単なるオブジェクトであることです。

console.log(([]) instanceof Object); // true
console.log(typeof []); // 'object'

配列のダックタイプ方法は、.length プロパティの存在を使用することです。しかし、配列のみが .length プロパティを持つという規則はないので、これは非常に弱いです。このパターンは通常、次のように見えます:

function processList(maybeArray) {
  if (!maybeArray.length) {
    return []
  }
  return maybeArray.map(i => i); // 文字通りコピー
}

上記のコードは、実際には maybeArray が配列かどうかをチェックしていません。それはするようなものですが、同じ行のコードである !maybeArray.length は、実際には配列の場合は、0 ではない非偽性の長さを持つ必要があるとも述べています(空であってはならない)。

しかし Array.isArray を使用すると次のように機能します:

console.log(Array.isArray({})); // false
console.log(Array.isArray(new Map())); // false
console.log(Array.isArray(new Set())); // false

console.log(Array.isArray([])); // true
console.log(Array.isArray(new Array())); // true

配列の内訳をチェックする方法の詳細については、JavaScript 配列型チェック - 「is array」対オブジェクト深掘りを参照してください。フレーム間の通信がある場合、Array, Object, Date などの組み込み JavaScript データ型の大きな問題は、コンストラクタや instanceof チェックが機能しないことです。

オブジェクトが特定のクラス/コンストラクタ関数のインスタンスであるかをチェックする

変数が React コンポーネントであることをチェックしたい場合、次のようにすることができます:

import React, { Component } from 'react';

const myComp = new Component();

function isReactComponent(maybeComponent) {
  return maybeComponent instanceof Component;
}

isReactComponent(myComp);
// true

isReactComponent({});
// false

これはコンストラクタ関数でも機能します:

function Dog (name) {
  this.name = name
}

const max = new Dog('Max');

console.log(max instanceof Dog); // true

もう一つ興味深いことは、プロトタイプチェーン/クラス階層を全て通じて動作することです:

console.log(({}) instanceof Object); // true
console.log((new Dog) instanceof Object); // true

オブジェクトがエラーかをチェックする

Error はただのコンストラクタ/クラスです。したがって、React.ComponentDog クラスについてチェックできるのと同じ方法です:

function isError(maybeError) {
  return maybeError instanceof Error;
}

isError(new Error('Something went wrong')); // true
isError(new EvalError()); // true
isError(new InternalError()); // true
isError(new RangeError()); // true
isError(new ReferenceError()); // true
isError(new SyntaxError()); // true
isError(new TypeError()); // true
isError(new URIError()); // true

MDN については、Fundamental Objects on MDN をご参照ください。

有効な JavaScript Date 文字列(解析可能な date-string)をチェックする

function isValidDateString(maybeDateString) {
  return !Number.isNaN(Number(new Date(maybeDateString)));
}

console.log(isValidDateString('abcd')); // false
console.log(isValidDateString(1234)); // true
console.log(isValidDateString('2019-06-23T22:00:26.861Z')); // true

上記の関数は実際には何かが有効な文字列かどうかをチェックしません。それが有効な日付に変換可能かどうかをチェックしています。

さまざまな目的のために、これは不正な日付文字列を捕捉するでしょうし、数字のタイムスタンプを渡させるよりもコストをかけて読みにくくすることはありません。もっと適切な名前は isConvertibleToDate かもしれません。数字を許可しないことは typeof maybeDateString === 'string' を追加するだけの問題です。

有効な JavaScript Date かどうかをチェックする

何かが有効な日付かどう
かをチェックするには、それが日付に変換可能かどうかをチェックするのと同じアプローチをとります。

function isValidDateObject(maybeDate) {
  return (
    typeof maybeDate === 'object' &&
    !Number.isNaN(Number(new Date(maybeDate))
  );
}

isValidDateObject('abc'); // false
isValidDateObject(1234); // false
isValidDateObject('2019-06-23T22:00:26.861Z'); // false
isValidDateObject(new Date('2019-06-23T22:00:26.861Z')); // true

または instanceof 方法を適用することもできます:

function isValidDateObject(maybeDate) {
  return maybeDate instanceof Date;
}

isValidDateObject('abc'); // false
isValidDateObject(1234); // false
isValidDateObject('2019-06-23T22:00:26.861Z'); // false
isValidDateObject(new Date('2019-06-23T22:00:26.861Z')); // true

これにはいくつかのクロスフレームの問題があり、誰かが独自のカスタムで非標準バージョンにグローバル

こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/hugo__df/javascript-data-type-check-cheatsheet-5b7d