配列の型注釈
多くのプログラミング言語で、配列とオブジェクト(連想配列)は、データ型の王様です。実際に人間がデータを作る場合には、配列(連続したデータ)と、オブジェクトや連想配列(ラベルの付いたデータ)は、理解しやすく利用しやすいです。
それでは配列やオブジェクトに型を付けていきましょう。
まずは配列です。JavaScriptの配列は、他のプログラミング言語と比べて非常に柔軟です。そのことは「どのような値が入っているのか分からず」、「どのようなアクセスが問題なのかも分からず」、「実用上の問題を引き起こす可能性が高い」ことを意味します。
それでは配列の例です。:(コロン)のあとに、配列に格納する型を書いて[]と書けばよいです。指定した型の値だけで構成された配列に制限できます。
let myArray: number[]; myArray = [10, 20, 30];
配列には、他の書き方もあります。Array<T>と書く方法です。この方法でも書いてみます。
let myArray2: Array<number>; myArray2 = [10, 20, 30];
では、こうしたデータ型については、どちらの記法を選べばよいのでしょうか。
これは、使用しているプログラムの内容によります。JSXのように<>が意味のある環境ならnumber[]のような書き方の方が安心でしょう。それ以外の場合は、プロジェクト全体で統一できるように選べばよいです。
タプル
JavaScriptにはタプルという型はありません。TypeScriptのタプルは、配列の各要素の位置に、データ型を指定したものを指します。
let myTuple: [number, string, boolean] = [10, "20", false];
TypeScriptのタプルは、配列の各要素に、どの型を指定するかを書きます。
オブジェクトの型注釈
オブジェクトの型注釈は、各プロパティに型を指定します。各プロパティの区切り文字は,(カンマ)を利用する方法と、;(セミコロン)を利用する方法があります。
let box: {x:number, y: number, z: number};
box = {x: 1, y: 2, z: 3};
let box2: {
x: number;
y: number;
z: number;
};
box2 = {x: 1, y: 2, z: 3};
また、オブジェクトの各プロパティの名前と値の型が固定の場合は、ユーティリティ型のRecordを使う方法もあります。
let box3: Record<string, number>;
box2 = {x: 1, y: 2, z: 3};
ユニオン型とリテラル型
「型を指定する場合には、数値か文字列のいずれかが欲しい」といったケースもあります。そうした時には、複数の型を結合したユニオン型を使います。ユニオン型は|(バーティカルバー)で型を結合します。
let statusCode: number | string; statusCode = 404; statusCode = "404";
リテラル型は、プリミティブ型の特定の値だけを代入可能にする型の表現です。ユニオンと組み合わせることで、特定の値だけを代入できる変数を作れます。
let statusCode: 400 | 404 | 500;
statusCode = 404;
let statusCode2:
| 400
| 404
| 500;
statusCode2 = 500;
any型
これまでの説明は、JavaScriptを知っていれば新たな知識をほとんど使わずに理解できる部分でした。しかし、ここからは少し特殊なTypeScript向けの知識になります。
まずはany型です。any型はどんな型でも受け入れる型です。推奨されない型ではありますが、JavaScriptからTypeScriptに移植している途中では、やむを得ず設定されることの多い型です。なぜならば、とりあえずany型を指定すれば、TypeScriptのコンパイルを突破できるからです。
let val: any;
val = 10;
val = "hellow";
val = true;
val = [10, 20];
val = {x: 1, y: 2};
void型
void型は、関数の戻り値で使用する型です。関数の実行の結果、戻り値を返さないことを明示するための型です。
例を挙げます。myPrint関数は、戻り値を戻さないことを想定した関数です。
// 戻り値のない関数
function myPrint(s: string): void {
console.log(s);
}
// 想定した使い方
myPrint("hello");
// 想定外の使い方
let res: string | undefined = myPrint("world");
例の最後の行では、myPrint関数から、stringかundefinedの値を得ようとしています。このコードを書くと、VSCode上でresの上にType 'void' is not assignable to type 'string | undefined'.(型 'void' は型 'string | undefined' に割り当てることはできません。)という警告が出ます。
またnpx tscでコンパイルすると、次のように結果が出ます。
main.ts:10:5 - error TS2322: Type 'void' is not assignable to type 'string'.
10 let res: string | undefined = myPrint("world");
~~~
Found 1 error in main.ts:10
こうしたエラーの検出により、関数の想定外の使用を防ぐことができます。
