TypeScriptとは
TypeScriptはJavaScriptへ静的な型チェックを加えた言語です。.tsファイルをコンパイラで検査し、JavaScriptへ変換して実行します。型は開発中の間違いを見つける助けになりますが、実行時には消えます。
| 役割 | TypeScript | JavaScript |
|---|---|---|
| 開発時 | 型を検査し、入力補完を助ける | 実行する処理を記述する |
| 実行時 | 型注釈は残らない | ブラウザやNode.jsが実行する |
const age: number = Number("20")のように、外部の文字列は実際の処理で数値へ変換します。型注釈を書くだけでは値は変わりません。練習環境を作る
Node.jsとnpmを導入済みの環境で、練習用ディレクトリへTypeScriptを開発用依存として入れます。プロジェクトごとに版を固定すると、別のプロジェクトへ影響しません。
mkdir typescript-practice
cd typescript-practice
npm init -y
npm install --save-dev typescript
npx tsc --initnode --version
npx tsc --versionv22.0.0
Version 5.x.x版番号は環境で異なります。生成されたtsconfig.jsonではstrictを有効にし、型の見落としを減らします。
npx tscを使いましょう。最初のプログラムを動かす
hello.tsを作り、次のコードを保存します。
const message: string = "こんにちは、TypeScript!";
console.log(message);npx tsc hello.ts
node hello.jsこんにちは、TypeScript!tscがhello.jsを生成し、Node.jsがJavaScriptを実行します。文末のセミコロンは省略できますが、この講座では表記を揃えるため記述します。
変数、定数、基本の型
再代入しない値はconst、後で値を変える必要がある場合だけletを使います。varはスコープが異なり混乱しやすいため、新しいコードでは通常使いません。
const userName: string = "Mity";
let age: number = 20;
const isStudent: boolean = true;
age = 21;
console.log(`${userName}さんは${age}歳です`);
console.log(isStudent);Mityさんは21歳です
true型推論
右辺から型が明らかな場合、TypeScriptは型を推論します。
const language = "TypeScript"; // stringと推論
let count = 3; // numberと推論
// count = "三"; // エラー: stringをnumberへ代入できない
console.log(language, count);TypeScript 3演算子
| 種類 | 演算子 | 例 |
|---|---|---|
| 計算 | + - * / % ** | 7 % 3は1 |
| 比較 | === !== > < >= <= | score >= 60 |
| 論理 | && || ! | isMember && hasTicket |
| 代入 | = += -= *= /= | total += 100 |
| 条件 | 条件 ? 真の場合 : 偽の場合 | age >= 18 ? "成人" : "未成年" |
const price = 500;
const count = 3;
const subtotal = price * count;
const tax = Math.floor(subtotal * 0.1);
console.log(`小計: ${subtotal}円`);
console.log(`合計: ${subtotal + tax}円`);小計: 1500円
合計: 1650円==より=== ==は型変換を伴う比較をするため、予想外の一致が起こります。型と値の両方を比較する===を基本にします。条件分岐
if、else if、elseで処理を切り替えます。条件は上から判定され、最初に真になった処理だけが実行されます。
const score = 82;
let result: string;
if (score >= 80) {
result = "合格(よくできました)";
} else if (score >= 60) {
result = "合格";
} else {
result = "再挑戦";
}
console.log(result);合格(よくできました)80点以上の条件を60点以上より前に置くことで、より具体的な条件を先に判定しています。
繰り返し
回数が決まっている処理にはfor、配列の値を順に使う場合はfor...ofが読みやすい書き方です。
for (let number = 1; number <= 3; number += 1) {
console.log(`${number}回目`);
}
const colors = ["赤", "青"];
for (const color of colors) {
console.log(color);
}1回目
2回目
3回目
赤
青whileを使う場合は、条件がいつ偽になるかを確認します。ブラウザやサーバーが応答しなくなる原因になります。配列を扱う
string[]は文字列だけを入れられる配列です。位置は0から数えます。
const scores: number[] = [40, 65, 80];
scores.push(95);
const passed = scores.filter((score) => score >= 60);
const labels = passed.map((score) => `${score}点`);
console.log(scores.length);
console.log(labels);4
[ '65点', '80点', '95点' ]filterは条件に合う値を集め、mapは各値を別の値へ変換した新しい配列を作ります。元の配列は書き換えません。
undefinedになります。設定のnoUncheckedIndexedAccessを有効にすると、その可能性を型にも反映できます。オブジェクトの形を型で表す
typeで、利用者データが持つプロパティの名前と型を定義します。?は値がない場合もあるプロパティです。
type User = {
readonly id: number;
name: string;
email?: string;
};
const user: User = { id: 1, name: "Mity" };
console.log(`${user.id}: ${user.name}`);
console.log(user.email ?? "メール未登録");1: Mity
メール未登録readonlyはTypeScriptの検査で再代入を防ぎます。??は左側がnullまたはundefinedのときだけ右側を使います。
関数へ型を付ける
引数には受け取れる型、戻り値には返す型を書きます。呼び出す側は必要な値を確認でき、関数内部では型に合う操作だけを使えます。
function calculateTotal(price: number, count: number): number {
const subtotal = price * count;
return subtotal + Math.floor(subtotal * 0.1);
}
console.log(calculateTotal(500, 3));
// calculateTotal("500", 3); // 型エラー1650値を返さない関数
function showMessage(message: string): void {
console.log(message);
}
showMessage("処理が完了しました");処理が完了しました複数の可能性をユニオン型で表す
|は「どちらか」の型です。利用前にtypeofで型を絞り込むと、それぞれに合う処理を書けます。
function formatId(id: number | string): string {
if (typeof id === "number") {
return `ID-${id.toString().padStart(4, "0")}`;
}
return id.toUpperCase();
}
console.log(formatId(25));
console.log(formatId("guest"));ID-0025
GUEST分岐の内側では、TypeScriptがidをそれぞれnumber、stringとして扱います。これを型の絞り込み(ナローイング)と呼びます。
nullとundefinedを安全に扱う
strictNullChecksが有効なら、値がない可能性を無視できません。オプショナルチェーン?.は、左側がnullまたはundefinedのとき、それ以降へアクセスせずundefinedを返す構文です。??と組み合わせると既定値を用意できます。
type Profile = { address?: { city?: string } };
const profile: Profile = {};
const city = profile.address?.city ?? "未設定";
console.log(city);未設定profile.addressはundefinedなので、?.は.cityを読み取らずundefinedを返します。その結果、??の右側にある「未設定」が使われます。
value!は、コンパイラに「この値はnullでもundefinedでもない」と開発者が宣言する構文です。型エラーを抑えるだけで、実行時に値の存在を確認しません。可能なら条件分岐や既定値で安全に処理します。練習問題:商品一覧を集計する
商品名、単価、個数を持つオブジェクトの配列を作り、各商品の小計と全商品の合計を表示してください。
解答例を見る
type Product = {
name: string;
price: number;
quantity: number;
};
const products: Product[] = [
{ name: "ノート", price: 200, quantity: 2 },
{ name: "ペン", price: 120, quantity: 3 },
];
let total = 0;
for (const product of products) {
const subtotal = product.price * product.quantity;
total += subtotal;
console.log(`${product.name}: ${subtotal}円`);
}
console.log(`合計: ${total}円`);ノート: 400円
ペン: 360円
合計: 760円