object - TypeScriptキーワード一覧
スポンサーリンク
「object」は「オブジェクト型」を表す型名として用いられます。他の基本型とは混ざらない型として用いられます。
TypeScript 2.2 で導入されています。
概要
(特筆の無いものは 「TypeScript Issue #1809: Suggestion: The `object` primitive type」での説明によります。)
- (型としての)キーワード「object」(または「object 型」)は基本型を除外したオブジェクト型を表します。
- 「object 型」は型「
{ }
」に似ていますが、number 型や string 型などの基本型を代入することができない型として扱われます(型「{ }
」はそれらの基本型を代入することができます)。 - 「object 型」のデータは「
{ }
」型(「Object」型を含む)および any 型にのみ代入が可能です。 - 「object 型」は前述の例外を除いて型「
{ }
」と同じ役割を持つため、「toString」や「hasOwnProperty」などの「Object 型」と同じメソッドを利用することができます。 - 「object 型」と他の基本型とのunion type(共用体型)になっている変数 x に対し、
typeof x === "object"
という構文を用いると、その条件(型ガード; type guard)下で実行されるコードにおいて x から基本型が除かれて object 型として扱われるようになります。- 厳密には、
typeof x === "object"
では基本型が取り除かれる型ガード(type guard)になります。(TypeScript 2.0 で導入; 関連: TypeScript Issue #4868: Expanded type guard suggestions)) - なお、
typeof null === "object"
は真であるため、「x: object | null
」に対して「typeof x === "object"
」で「object 型」に限定できないことに注意が必要です。
- 厳密には、
- 一般的にオブジェクト型は、グローバルの「Object」型(Objectインターフェイス)と同じプロパティー(同名のプロパティーがあればそれを除く)を持つ型として扱われます。(TypeScript/spec.md 「3.11.1 Apparent Members」)
- object 型は他にプロパティーを持たないオブジェクト型となるため、見かけ上のメンバーが「Object」型と一致することになり、結果前述の通り「Object」型に代入可能となります。
- なお、逆に「Object」型は「基本型」ではないので「object 型」に代入可能となります。ただし「Object」型にはプリミティブ型を代入可能なので、これは意図しない動作になる可能性があります。
キーワード情報
- 「object」は識別子としては予約されていません。(ユーザー定義の識別子として利用できます。)
- 「object」は型名として予約されています。(ユーザー定義の型名として利用できません。)
詳細
「object 型」は通常は「オブジェクト型」として扱われますが、それと同時に「プリミティブ型ではない」すなわち「number・string・symbol などの基本型ではない」ことを明確に示す型になります。「Object 型」の変数には数値やboolean値などを代入できるのに対し、「object 型」の変数には代入できずエラーとなります。
let x: object; // object 型変数
let y: Object; // Object 型変数
x = { data: 10 }; // オブジェクトデータを代入
x = 'hello text'; // ERROR: TS2322: 文字列は object 型に割り当てられない
y = 'hello text'; // 文字列は Object 型には割り当て可能
y = x; // object 型は「{ }」型と同等、「{ }」は他にフィールドを持たないために
// 「Object」型と同等なので、Object 型に object 型データを割り当て可能
なお、Function 型自身が厳密に Object の部分型(派生型)となっているため(ES2015の仕様、Function.prototype
の [[Prototype]]
が %ObjectPrototype%
)、関数型のデータは object 型の変数に代入可能です。また、型ガードで object 型に対して関数かどうかの判定をすると、そのガード下では never とならず関数として利用できます。
let obj: object; // object 型変数
.
.
.
if (typeof obj === 'function') {
// このブロックでは obj を関数(Function 型)として扱える
obj();
}
ただし、「null」値は typeof の結果が "object" になるため、「strictNullCheck」のオプションが有効である場合、「typeof x === "object"
」という型ガードでは「null 型」が入る可能性があります。
// (「strictNullCheck」が有効である場合)
let obj: object | null | undefined; // Nullable な object 型変数
.
.
.
if (typeof obj === 'object') {
// このブロックで obj は「object | null」型となり、依然として Nullable となる
// (undefined は typeof が 'undefined' なのでそれは取り除かれる)
console.log(obj.toString()); // ERROR: TS2531: obj が null の可能性がある
}
object 型データの利用
「object 型」のデータは「プリミティブ型ではない Object 型」以上の情報を持たず、「any」の意味を持つわけでもないため、通常利用することは稀です。多くの場合、「interface」などで定義されたより具体的な型を指定するか、「任意の型を利用したい」という意味で any 型を用いることが多いと考えられます。
object 型は「プリミティブ型ではない」ということを用いて、typeof の結果が "object" (および "function")であることを期待したい箇所で利用することができます。例として、プリミティブ型は任意のプロパティー(フィールド)を動的に追加することができない(ES2015の仕様)ので、引数に対してそのような処理を行う関数では、その引数の型を「object」とすることで、意図せずプリミティブ型のデータが渡されることを防ぐことができます。
// オブジェクトに対してプロパティー追加を伴う何かしらの加工を行う関数
function writeMarker(obj: object) {
// object 型そのものはほとんどのプロパティーを持たない型になるので、
// 独自のプロパティーを入れる場合は any に変換して型チェックを省略するようにする
(obj as any)['.$marker'] = true;
}
let o1 = {};
writeMarker(o1); // OK
let o2: number = 10;
writeMarker(o2); // ERROR: TS2345: number 型は object 型に割り当てられない