All Articles

TypeScript における Object、object、{} の違いについて

概要

TypeScriptでオブジェクトを型で表現するには以下の方法がある。

  1. オブジェクトリテラル表記
  2. Object
  3. object
  4. {} (Empty object literal, 空のオブジェクトリテラル表記)

形状が決まっていればオブジェクトリテラル表記を用いる。
必要とあらば、それに対してinterfacetype aliasで別名を付けるなどする。

しかし、形状が決まっていないオブジェクトを型で表現したくなった。
欲しくなったのは
「明示的に値がundefinedとなっているプロパティを再帰的に除く」
という関数を定義しているときだった。

function excludedUndefined(obj: /* ココ */) {
  // オブジェクトのプロパティから値が undefined のものを削除する処理
};

/* ココ */を埋めようとするとObjectobject{}が頭に思い浮かんできた。
どれもオブジェクトを表現してくれそうだ。

今後、正しい理解のもと気持ちよく型を指定する日々を過ごすためにも
ここで一回整理しておく。

結論

ObjectObjectコンストラクタを表現する型
{}は特殊で、nullundefined以外を許容する型

objectを使おう

本題

Object

まずコイツだが、TypeScript公式ドキュメントで使うなと言われちゃっている。

Don’t ever use the types Number, String, Boolean, Symbol, or Object These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code.

Don't ever useに「使うんじゃねぇぞ」という強い意思を感じる。

NumberStringなどのことを考えると、まぁそうだよねと頷けるね。
ドキュメントを見た感じだと、
普通にJavaScriptを書く分には触る必要のない、
非プリミティブなボックス化されたオブジェクトを指す型とのことだ。

Objectコンストラクタを指していると思ってよいだろう。
非プリミティブなボックス化されたオブジェクトってのは多分↓のようなことを指している。

'おにぎり'.length
// プリミティブな値がプロパティを持っている…??
// いいえ、内部的には↓と同様の挙動で
// Stringコンストラクタでラップされた状態になっている
new String('おにぎり').length
// ↑ Stringコンストラクタから得られるオブジェクトこそ
// 非プリミティブなボックス化されたオブジェクトなのだ

ちなみに「非プリミティブなボックス化されたオブジェクト」は雰囲気を翻訳しただけで、
日本語でこう表現されるのが一般的かどうかまではわからない。あしからず。

{} (Empty object literal, 空のオブジェクトリテラル表記)

コイツはどうもプロパティを持たないオブジェクトを表現しているように見受けられる。
しかし、予想に反して特殊な型だった。

empty object literal sample

…?
なんだか大変なことになっているようだが。
ちなみに、赤い下線が出ていれば型チェックでエラーになっている。
オライリーの「プログラミングTypeScript ――スケールするJavaScriptアプリケーション開発」を見てみたらこう書かれていた。

すべての型は−nullとundefinedを除いて−空のオブジェクト型に割り当て可能ですが、この挙 動は扱いづらいものです。空のオブジェクト型は、できるだけ避けるようにしてください。

{}も基本的には使わないほうが良いであろうということが判明。

object

まぁ、消去法でコイツしか無いわけだ。
公式ドキュメントの Basic Types にいるわけだから
普通に学んでいけばコイツを使うことになるはずだね。

object is a type that represents the non-primitive type, i.e. anything that is not number, string, boolean, bigint, symbol, null, or undefined.

非プリミティブを表現する型、と説明されている。
なんとなく、オブジェクトを表現する型とは思っていたが
このような説明文で表現される得るのかと気づきを得た。

object type sample code

いい感じだ。
配列はもちろんエラーにはなってないので含めない場合は
Array.isArrayをつかってよしなにやるのが良さそうだ。

typeof array sample code

↑ 配列はあくまで「特殊な振る舞いをするオブジェクト」である
typeof演算子を使うと'object'と評価される

まとめ

結論は冒頭にまとめたとおりだ。
これで人に聞かれても答えられるくらいにはなった気がする。

余談だけど、最近4Kモニターを買った。
LG の 27UK850-W ってやつだ。

27インチで Type-C 給電にも対応したやつを少し奮発して買った。
Type-C を Macbook にさすと PC への給電と映像出力ができるのはとても体験がいい。
しかも、モニターに USB TypeA のメスポートがあり、
キーボードなどもつなぐことができる。
思っていた以上に体験が良かった。

ただ、 FHD ディスプレイ4枚の代わりにするには文字が小さくなりすぎた。
やはり最低でも40インチは無いと厳しいだろう。

Amazon のポイントもどっさり入った。やったね

参考文献