🙄
【TS】オブジェクト型を判定する
概要
Typescriptである値がオブジェクト型かどうかを判定する際に単純にtypof arg ==== 'object'だけをしていたので備忘として整理しました。
有識者の方にいろいろアドバイスをいただきました!ありがとうございます!
結論
今回判定したいオブジェクトは、
- オブジェクトリテラル
- 自作クラスで作成
new
const isObject = (arg:any): arg is object => {
if (typeof arg !== 'object' || arg === null) return false;
if (Object.prototype.toString.call(arg) !== '[object Object]') return false;
const proto = Object.getPrototypeOf(arg);
return proto === null || proto === Object.prototype;
}
解説
typeof arg === 'object'
対象の値の型がobjectかどうかを判定。ただ実はこれnullや配列、new DateのようなJavascriptの組み込みオブジェクトまでtrueになる。
要件によってはむしろこれでOKってパターンがあるかもだけど、今回オブジェクト判定して欲しいのは以下のようなキーと値から構成される純粋なオブジェクトだけに絞りたい。だからtypeof arg === 'object'だけだと想定外のものもtrueになってしまう。
/// true判定したい純粋オブジェクト
const test = {
name:"Bob",
age:30
}
// false判定して欲しいもの
const arr = [](配列)
const date = new Date();(組み込み関数)
const funct = () => {}; (関数)
arg.constructor === Object
.constructorプロパティは、対象のオブジェクトがどのコンストラクタ関数から生成されたかを示す。arg.constructor === ObjectはObject型のコンストラクタ関数から生成されているかどうかを判定している。
arg.constructor === Objectだけでよくない?
と、思ったのですが、これだけだと純粋なオブジェクト判定はできない模様。なので、各条件が除外するものを一覧にまとめました。
| 条件 | 除外するもの |
|---|---|
typeof arg === 'object' |
プリミティブ型(number, string, boolean, symbol, undefined)を除外 |
arg !== null |
nullを除外 |
arg.constructor === Object |
配列、組込オブジェクト(Date, RegExpなど)、関数(function)を除外 |
Discussion
それだと
みたいな純粋オブジェクトが判定できないのでは……?
とも思ったが、 structuredClone とかでは維持されないし、ままいいか……。
ありがとうございます!たしかに上記の考慮が足りていませんでした...!
ちょっと脱線してしまうのですが、上記のようなプロトタイプチェーンを意図的に切るオブジェクトってどのような時に使われますか?
__proto__プロパティに意味を持たせたくないときとかでしょうか……。Object.create(null) と同様に
__proto__を設定してもただの通常プロパティと同じ扱いになり、プロトタイプ汚染攻撃対策となります。ありがとうございます!「プロトタイプ汚染攻撃対策」を恥ずかしながら知りませんでした。
上記のようなオブジェクトを含めて、オブジェクト判定するロジックを検討してみました!もしよければご確認とご助言をいただけますと幸いです。
いいと思いますー。
ご丁寧にいろいろありがとうございます!!!