TypeScript入門:型の種類と環境構築をやさしく解説
はじめに
TypeScriptを使い始めたいけれど、どの型をどう使えばいいのかわからない。そんな疑問を持っている方は多いのではないでしょうか。TypeScriptはJavaScriptに型の仕組みを加えた言語です。型があることで、コードの間違いを実行前に見つけられます。
この記事では、TypeScriptの環境構築から基礎的な型の種類までをやさしく解説します。コード例を交えながら、プリミティブ型・配列・オブジェクト型・readonlyの使い方まで、ひと通りの基礎を身につけられる内容です。
TypeScript開発環境の構築
TypeScriptのコードを書いて動かすには、いくつかのツールが必要です。ここでは、環境構築の手順を順番にご説明します。
以下の図は、TypeScriptの開発環境で必要になるツールの関係を示しています。
flowchart TD
A[TypeScriptコード .ts] --> B[tsc コンパイラ]
B --> C[JavaScriptコード .js]
C --> D[Node.js で実行]
A --> E[ts-node]
E --> D
このように、TypeScriptのコードは直接実行できません。tscでJavaScriptに変換してから実行するか、ts-nodeで一括処理します。
tscによるコンパイルと実行
まず、エディタとしてVisual Studio Code(VS Code)を用意します。次に、TypeScriptのコンパイラをインストールします。Node.jsがまだ入っていない場合は、先にNode.js公式サイトからインストールしてください。
$ npm install -g typescript
インストールが完了したら、hello.ts というファイルを作成します。
const message: string = "Hello TypeScript";
console.log(message);
このファイルを tsc コマンドでコンパイルします。
$ tsc hello.ts
同じディレクトリに hello.js が生成されます。中身を見ると、const が var に変わり、型アノテーション(: string)が消えています。TypeScriptの型情報は、コンパイル後のJavaScriptには残りません。
var message = "Hello TypeScript";
console.log(message);
生成された hello.js をNode.jsで実行すると、Hello TypeScript と表示されます。
$ node hello.js
Hello TypeScript
ts-nodeによる簡易実行
tsc でコンパイルしてから node で実行するという2段階の手順は少し手間です。ts-nodeを使えば、この手順を1回にまとめられます。
$ npm install -g ts-node
$ ts-node hello.ts
Hello TypeScript
ts-nodeは内部でコンパイルと実行を同時に行っています。開発中のちょっとした動作確認にはとても便利です。
tsconfig.jsonの役割と基本設定
TypeScriptプロジェクトでは、コンパイラの設定を tsconfig.json にまとめます。このファイルがプロジェクトのルートにあると、tsc コマンド実行時に自動で設定が読み込まれます。
{
"compilerOptions": {
"outDir": "./dist",
"target": "ES2020",
"module": "ES2020"
},
"include": ["src//*"]
}
主な設定項目は以下のとおりです。
target: 出力するJavaScriptのバージョンを指定しますmodule: モジュールシステムを指定しますoutDir: コンパイル結果の出力先ディレクトリですstrict: すべての厳格な型チェックを有効にしますinclude: コンパイル対象のファイルパターンですexclude: コンパイルから除外するファイルパターンです
チーム開発では、このファイルをリポジトリに含めることで設定を共有できます。上記は一部のオプションのみです。より詳しくは公式ドキュメントを参照してください。
TypeScript公式 tsconfig リファレンス
プリミティブ型の種類と型アノテーション
TypeScriptの型は、JavaScriptのデータ型に対応しています。ここでは、もっとも基本となるプリミティブ型と、型を指定する方法をご紹介します。
TypeScriptで扱えるプリミティブ型は以下の7つです。
string: 文字列number: 数値(整数・浮動小数点のどちらも含みます)boolean: 真偽値(true/false)null: 値が存在しないことを明示する型undefined: 値が未定義であることを表す型symbol: 一意の識別子を表す型(ES2015以降)bigint: 大きな整数を扱う型(ES2020以降)
このうち、日常的によく使うのは string、number、boolean の3つです。
型アノテーションと型推論
TypeScriptで変数に型を指定するには、変数名の後にコロンと型名を書きます。これを型アノテーションと呼びます。
const capital: string = "Tokyo";
const zipCode: number = 1000001;
const isResident: boolean = true;
一方、型を書かなくても、TypeScriptは代入された値から型を自動で判断します。これが型推論です。
const age = 25; // number型と推論されます
const name = "太郎"; // string型と推論されます
const isActive = true; // boolean型と推論されます
TypeScriptの型推論はとても賢いので、明示的に型を書かなくても問題ない場面は多いです。ただし、関数のパラメータなど推論が効かない場面では、型アノテーションが必要になります。
型推論の仕組みについて詳しく知りたい方は、以下の記事をご覧ください。
string型・number型・boolean型の使い方
もっともよく使うプリミティブ型を見てみましょう。
let userName: string = "Michael";
let age: number = 30;
let isActive: boolean = true;
型に合わない値を代入しようとすると、TypeScriptはエラーを出します。
userName = 123;
// Error: Type 'number' is not assignable to type 'string'
このように、型のミスマッチをコンパイル時に検出できるのがTypeScriptの大きな利点です。
undefinedとnullの使い分け
JavaScriptには「値がない」ことを表す方法が2つあります。undefined は値が未定義であること、null は意図的に値がないことを示します。
const a: undefined = undefined;
const b: null = null;
実際の開発では、undefined を使う場面の方が多い傾向にあります。オプショナルプロパティの既定値は undefined ですし、オプショナルチェーンも undefined を返します。
null は、設定ファイルの「まだ値が入っていないフィールド」や、データベースのNULL値のマッピングなどで使われます。
interface Config {
apiKey: string | null; // 将来設定される予定のフィールド
timeout: number;
}
チーム内で undefined と null の使い分けルールを決めておくと、コードの一貫性が保てます。
strictNullChecksの重要性
tsconfig.json の strictNullChecks オプションは、undefined と null の扱いに大きく影響します。
false の場合、どの型にも undefined や null を代入できてしまいます。
// strictNullChecks: false の場合
let value: number = 10;
value = undefined; // エラーなし
value = null; // エラーなし
true にすると、undefined や null はそれぞれの型としてのみ扱われます。
// strictNullChecks: true の場合
let value: number = 10;
value = undefined; // エラー
value = null; // エラー
undefined を許容したい場合は、ユニオン型を使います。
let value: number | undefined = 10;
value = undefined; // OK
strictNullChecks は true に設定するのが推奨です。型の安全性が格段に高まります。
配列型・タプル型・オブジェクト型の使い方
プリミティブ型に加えて、複数の値をまとめて扱うための型も重要です。ここでは配列、タプル、オブジェクトの型について解説します。
以下の図は、TypeScriptの型の分類を整理したものです。
flowchart LR
A[TypeScriptの型] --> B[プリミティブ型]
A --> C[オブジェクト型]
B --> D[string]
B --> E[number]
B --> F[boolean]
B --> G[null / undefined]
B --> H[symbol / bigint]
C --> I[配列]
C --> J[タプル]
C --> K[オブジェクト]
配列型の書き方
配列の型には、2つの書き方があります。
const scores: number[] = [80, 90, 100];
const names: Array = ["Alice", "Bob"];
number[] と Array は同じ意味です。一般的には number[] のような短い書き方が好まれます。配列内の要素は、指定した型で統一されることが保証されます。
タプル型で異なる型を組み合わせる
タプル型は、固定長の配列を定義するための型です。配列型では要素の型が統一されますが、タプル型なら異なる型を組み合わせられます。
const person: [string, number] = ["太郎", 25];
1番目の要素は string、2番目は number という形で、位置ごとに型を指定できます。
オブジェクト型とオプショナルプロパティ
オブジェクトには、プロパティごとに型を定義できます。
const person: { name: string; age: number } = {
name: "太郎",
age: 25,
};
プロパティが足りない場合や、余分なプロパティがある場合はエラーになります。
一部のプロパティが省略可能な場合は、? をつけてオプショナルプロパティにします。
const person: { name: string; age?: number } = {
name: "太郎",
};
この場合、age の型は number | undefined になります。値が渡されなければ undefined が入ります。
なお、TypeScriptには object という型もありますが、プロパティの情報を持っていないためプロパティへのアクセスができません。実用的ではないので、具体的なプロパティと型を定義するオブジェクト型を使うようにしましょう。
オブジェクト型に名前を付けて再利用する方法として、interfaceがあります。詳しくは以下の記事で解説しています。
readonlyとas constによる不変性の表現
変数やプロパティを変更できないようにしたい場面は、開発中によくあります。TypeScriptでは readonly と as const を使って、型レベルで不変性を表現できます。
readonlyで変更を防ぐ
readonly をプロパティに付けると、そのプロパティへの再代入を防止できます。
interface User {
readonly id: number;
name: string;
}
const user: User = { id: 1, name: "Alice" };
user.id = 2; // Error: Cannot assign to 'id' because it is a read-only property.
すべてのプロパティを一括で readonly にしたい場合は、ユーティリティ型の Readonly を使います。
type ReadonlyUser = Readonly;
const readonlyUser: ReadonlyUser = { id: 1, name: "Alice" };
readonlyUser.name = "Bob"; // Error
as constでリテラル型に固定する
as const は、すべてのプロパティに readonly を付与し、さらにリテラル型として確定させます。
const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3,
} as const;
config.apiUrl = "https://other.com"; // Error
as const を使うと、apiUrl の型は string ではなく "https://api.example.com" というリテラル型になります。設定値のように変更されたくないオブジェクトに適しています。
any型を避けてunknown型を使う
any 型は「どんな型でもあり」という意味で、型チェックが完全に無効になります。
const value: any = 123;
value.toUpperCase(); // TypeScriptはエラーを出さないが、実行時にエラーになる
TypeScriptが提供する型の保護を完全に放棄することになるため、原則として使用を避けましょう。
型がわからない場合は、any の代わりに unknown 型を使うと安全です。unknown 型の値を使うには、型を絞り込む必要があります。
let input: unknown = "hello";
if (typeof input === "string") {
console.log(input.toUpperCase()); // OK
}
このように型ガードで絞り込んでから使うことで、安全性を保てます。
終わりに
この記事では、TypeScriptの環境構築から基礎的な型の種類までを解説しました。tscによるコンパイル、tsconfig.jsonの設定、プリミティブ型や配列・オブジェクト型の使い方、そしてreadonly・as constによる不変性の表現まで、TypeScriptの基礎をひと通りカバーしています。
TypeScriptの型システムは、「このデータはどんな形をしているか」を記述する仕組みです。基本的な型をしっかり理解しておくと、ユニオン型やジェネリクスといった発展的な機能もスムーズに学べます。まずは今回の内容を手元で試しながら、型のある開発に慣れていきましょう。
TypeScriptとECMAScriptの関係や、型システムの背景について理解を深めたい方はこちらもご覧ください。
TypeScript公式ドキュメント
Node.js公式サイト
コメントを残す