メインコンテンツまでスキップ

オブジェクトの型注釈 (type annotation)

TypeScriptでオブジェクトの型注釈は、JavaScriptオブジェクトリテラルのような書き方で、オブジェクトプロパティをキーと値の型のペアを書きます。

ts
let box: { width: number; height: number };
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^型注釈
box = { width: 1080, height: 720 };
ts
let box: { width: number; height: number };
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^型注釈
box = { width: 1080, height: 720 };

オブジェクトの型注釈をしておくと、型の誤りをコンパイラーが警告してくれるようになります。

ts
let box: { width: number; height: number };
// 誤ってプロパティに文字列を代入した
box = { width: "1080", height: 720 };
Type 'string' is not assignable to type 'number'.2322Type 'string' is not assignable to type 'number'.
// 誤ってheightを指定し忘れた
box = { width: 1080 };
Property 'height' is missing in type '{ width: number; }' but required in type '{ width: number; height: number; }'.2741Property 'height' is missing in type '{ width: number; }' but required in type '{ width: number; height: number; }'.
ts
let box: { width: number; height: number };
// 誤ってプロパティに文字列を代入した
box = { width: "1080", height: 720 };
Type 'string' is not assignable to type 'number'.2322Type 'string' is not assignable to type 'number'.
// 誤ってheightを指定し忘れた
box = { width: 1080 };
Property 'height' is missing in type '{ width: number; }' but required in type '{ width: number; height: number; }'.2741Property 'height' is missing in type '{ width: number; }' but required in type '{ width: number; height: number; }'.

プロパティの区切り文字には、オブジェクトリテラルのようにカンマ,も使えますが、セミコロン;を用いるほうを推奨します。理由は、コード整形ツールPrettierがオブジェクトの型注釈を直すとき、カンマをセミコロンに置き換えるためです。

オブジェクトの型注釈は途中で改行することもできます。改行した場合、プロパティの区切り文字は省略できます。

ts
let box: {
width: number;
height: number;
};
box = { width: 1080, height: 720 };
ts
let box: {
width: number;
height: number;
};
box = { width: 1080, height: 720 };

インラインの型注釈の代わりに、型エイリアスを使った型注釈の書き方もできます。

ts
// 型エイリアス
type Box = { width: number; height: number };
let box: Box = { width: 1080, height: 720 };
// ^^^型注釈
ts
// 型エイリアス
type Box = { width: number; height: number };
let box: Box = { width: 1080, height: 720 };
// ^^^型注釈

📄️ 型エイリアス

TypeScriptでは、型に名前をつけられます。名前のついた型を型エイリアス(タイプエイリアス; type alias)と呼びます。

メソッドの型注釈

オブジェクトの型注釈には、メソッドの型注釈を書くこともできます。書き方はJavaScriptのメソッド構文に引数と戻り値の型注釈を加えたようなものになります。

ts
let calculator: {
sum(x: number, y: number): number;
};
 
calculator = {
sum(x, y) {
return x + y;
},
};
ts
let calculator: {
sum(x: number, y: number): number;
};
 
calculator = {
sum(x, y) {
return x + y;
},
};

メソッドの型注釈は関数構文の書き方もできます。

ts
let calculator: {
sum: (x: number, y: number) => number;
};
ts
let calculator: {
sum: (x: number, y: number) => number;
};

メソッド構文(method syntax)の型注釈と関数構文(function syntax)の型注釈は、基本的に同じ意味ですが、コンパイラーオプションのstrictFunctionTypesを有効にした場合に関数構文の書き方は、メソッド引数のチェックが双変(bivariant)から共変(covariant)へと厳格になります。この詳細についてはstrictFunctionTypesの説明を参照してください。

📄️ strictFunctionTypes

引数型の変性のチェックを厳しくする

オブジェクトの型推論

オブジェクトの値を変数宣言で代入する場合、型注釈を省略できます。値から型が自動的に判別されます。これを型推論といいます。

ts
let box = { width: 1080, height: 720 };
let box: { width: number; height: number; }
ts
let box = { width: 1080, height: 720 };
let box: { width: number; height: number; }

メソッドを持つオブジェクトリテラルでも型推論が働きます。ただし、メソッドの場合は引数の型注釈は必要です。

ts
let calculator = {
sum(x: number, y: number) {
return x + y;
},
};
calculator;
let calculator: { sum(x: number, y: number): number; }
ts
let calculator = {
sum(x: number, y: number) {
return x + y;
},
};
calculator;
let calculator: { sum(x: number, y: number): number; }

Record<Keys, Type>

連想配列のようなキーバリューのオブジェクトの型を定義する場合、ユーティリティ型のRecordを使う方法もあります。

ts
let foo: Record<string, number>;
foo = { a: 1, b: 2 };
ts
let foo: Record<string, number>;
foo = { a: 1, b: 2 };

📄️ Record<Keys, Type>

キー・バリューからオブジェクト型を作る

object

オブジェクトの型注釈にはobject型を用いることもできます。

ts
let box: object;
box = { width: 1080, height: 720 };
ts
let box: object;
box = { width: 1080, height: 720 };

object型の使用はお勧めしません。第1の理由は、object型には何のプロパティがあるかの情報がないためです。そのため、box.widthを参照するとコンパイルエラーになります。

ts
box.width;
Property 'width' does not exist on type 'object'.2339Property 'width' does not exist on type 'object'.
ts
box.width;
Property 'width' does not exist on type 'object'.2339Property 'width' does not exist on type 'object'.

第2の理由はどんなオブジェクトでも代入できるからです。期待しない値も代入できてしまうので、コードの問題に気づきにくくなります。

ts
let box: object;
box = { wtdih: 1080, hihget: 720 }; // スペルミス
ts
let box: object;
box = { wtdih: 1080, hihget: 720 }; // スペルミス

オブジェクトを型注釈する場合は、object型はできるだけ使わずに、プロパティまで型を定義することをお勧めします。

学びをシェアする

・TypeScriptでオブジェクトを型注釈するには、プロパティキーごとに型を定義する
例: { width: number; height: number}
・変数にオブジェクトを代入すると型推論が効く
・安全性の観点からobject型を用いるのは避ける

『サバイバルTypeScript』より

この内容をツイートする

関連情報

📄️ object、Object、{}の違い

TypeScriptではオブジェクトの型注釈をするとき、プロパティの型まで指定するのが一般的です。

📄️ インターフェース

インターフェースはクラスが実装すべきフィールドやメソッドを定義した型です。クラスはインターフェースを実装することで、インターフェースが求めるメソッド名や引数の型に則っているかをチェックすることができます。