条件分岐
if文
const age: number = 20;
if (age >= 20) {
console.log("成人です");
} else if (age >= 13) {
console.log("ティーンエイジャーです");
} else {
console.log("子供です");
}
型による条件分岐
function processValue(value: string | number): void {
if (typeof value === "string") {
// この中ではvalueはstring型
console.log(value.toUpperCase());
} else {
// この中ではvalueはnumber型
console.log(value.toFixed(2));
}
}
switch文
type Status = "pending" | "approved" | "rejected";
function getStatusMessage(status: Status): string {
switch (status) {
case "pending":
return "審査中です";
case "approved":
return "承認されました";
case "rejected":
return "却下されました";
// defaultは不要(網羅性チェック)
}
}
網羅性チェック
type Color = "red" | "green" | "blue";
function getColorCode(color: Color): string {
switch (color) {
case "red":
return "#FF0000";
case "green":
return "#00FF00";
case "blue":
return "#0000FF";
default:
// 到達不可能なコード
const _exhaustive: never = color;
return _exhaustive;
}
}
// 新しい色を追加するとコンパイルエラーで気づける
三項演算子
const age: number = 20;
const status: string = age >= 20 ? "成人" : "未成年";
// ネストは避ける
const message: string =
age >= 65 ? "シニア" :
age >= 20 ? "成人" :
"未成年";
型ガード
typeof ガード
function double(value: string | number): string | number {
if (typeof value === "string") {
return value + value;
}
return value * 2;
}
instanceof ガード
class Dog {
bark(): void {
console.log("ワン!");
}
}
class Cat {
meow(): void {
console.log("ニャー!");
}
}
function makeSound(animal: Dog | Cat): void {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
in ガード
interface Bird {
fly(): void;
}
interface Fish {
swim(): void;
}
function move(animal: Bird | Fish): void {
if ("fly" in animal) {
animal.fly();
} else {
animal.swim();
}
}
カスタム型ガード
interface User {
type: "user";
name: string;
}
interface Admin {
type: "admin";
name: string;
permissions: string[];
}
// 型述語(type predicate)
function isAdmin(person: User | Admin): person is Admin {
return person.type === "admin";
}
function greet(person: User | Admin): void {
if (isAdmin(person)) {
console.log(`管理者 ${person.name} さん、権限: ${person.permissions.join(", ")}`);
} else {
console.log(`${person.name} さん、こんにちは`);
}
}
ループ
for文
// 基本のfor文
for (let i: number = 0; i < 5; i++) {
console.log(i);
}
// for...of(値を取得)
const fruits: string[] = ["apple", "banana", "orange"];
for (const fruit of fruits) {
console.log(fruit);
}
// for...in(キーを取得)
const user = { name: "太郎", age: 25 };
for (const key in user) {
console.log(key); // "name", "age"
}
for…of と型
// 配列
const numbers: number[] = [1, 2, 3];
for (const num of numbers) {
// num は number 型
console.log(num * 2);
}
// Map
const map = new Map<string, number>([
["one", 1],
["two", 2]
]);
for (const [key, value] of map) {
// key: string, value: number
console.log(`${key}: ${value}`);
}
// Set
const set = new Set<string>(["a", "b", "c"]);
for (const item of set) {
console.log(item);
}
while文
let count: number = 0;
while (count < 5) {
console.log(count);
count++;
}
// do...while
let input: string;
do {
input = prompt("'exit'と入力してください") || "";
} while (input !== "exit");
break と continue
// break
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // ループを抜ける
}
console.log(i);
}
// continue
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
continue; // 次の反復へ
}
console.log(i); // 奇数のみ
}
// ラベル付きbreak
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // 外側のループを抜ける
}
console.log(i, j);
}
}
配列メソッドとループ
const numbers: number[] = [1, 2, 3, 4, 5];
// forEach
numbers.forEach((num: number, index: number) => {
console.log(`${index}: ${num}`);
});
// map
const doubled: number[] = numbers.map((num) => num * 2);
// filter
const evens: number[] = numbers.filter((num) => num % 2 === 0);
// find
const found: number | undefined = numbers.find((num) => num > 3);
// some / every
const hasEven: boolean = numbers.some((num) => num % 2 === 0);
const allPositive: boolean = numbers.every((num) => num > 0);
// reduce
const sum: number = numbers.reduce((acc, num) => acc + num, 0);
非同期ループ
// for...of と async/await
async function processItems(items: string[]): Promise<void> {
for (const item of items) {
await processItem(item);
}
}
// 並列処理
async function processItemsParallel(items: string[]): Promise<void> {
await Promise.all(items.map((item) => processItem(item)));
}
async function processItem(item: string): Promise<void> {
// 非同期処理
}
実践例:フォームバリデーション
interface ValidationRule {
type: "required" | "minLength" | "maxLength" | "pattern";
value?: number | RegExp;
message: string;
}
interface ValidationResult {
valid: boolean;
errors: string[];
}
function validate(input: string, rules: ValidationRule[]): ValidationResult {
const errors: string[] = [];
for (const rule of rules) {
switch (rule.type) {
case "required":
if (!input.trim()) {
errors.push(rule.message);
}
break;
case "minLength":
if (typeof rule.value === "number" && input.length < rule.value) {
errors.push(rule.message);
}
break;
case "maxLength":
if (typeof rule.value === "number" && input.length > rule.value) {
errors.push(rule.message);
}
break;
case "pattern":
if (rule.value instanceof RegExp && !rule.value.test(input)) {
errors.push(rule.message);
}
break;
}
}
return {
valid: errors.length === 0,
errors
};
}
// 使用例
const emailRules: ValidationRule[] = [
{ type: "required", message: "メールアドレスは必須です" },
{ type: "pattern", value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: "メールアドレスの形式が正しくありません" }
];
const result = validate("test@example.com", emailRules);
console.log(result.valid); // true
まとめ
if文で条件分岐、型ガードで型を絞り込みswitch文と網羅性チェックで安全なコードfor...ofで配列やMapをイテレート- 型述語(
is)でカスタム型ガードを定義 - 配列メソッドで関数型スタイルのループ
次回は関数と型について詳しく学びます。