LESSON 30分

文字列操作をマスターしよう

ストーリー

「最初の実務タスクだ」田中先輩がチケットを見せた。

「ユーザーから送られてくるデータを検証・整形する機能を作ってくれ。 メールアドレスの検証、名前の正規化、検索キーワードの分割... 全部文字列操作だ」

「文字列操作って、地味に大変そうですね」

「地味だが超重要だ。業務コードの3割は文字列操作だと言っても過言じゃない。 ここをマスターすれば、一気に戦力になれるぞ」


テンプレートリテラル

バッククォート(`)で囲む文字列です。変数の埋め込みや改行が自在にできます。

typescript
const name = "田中";
const age = 28;

// テンプレートリテラル(推奨)
const message = `こんにちは、${name}さん。${age}歳ですね。`;

// 従来の文字列結合(非推奨)
const oldMessage = "こんにちは、" + name + "さん。" + age + "歳ですね。";

// 複数行
const html = `
<div class="card">
  <h2>${name}</h2>
  <p>年齢: ${age}</p>
</div>
`;

// 式の埋め込み
const priceWithTax = `税込: ${Math.floor(1980 * 1.1)}円`;
// "税込: 2178円"

基本的な文字列メソッド

長さと検索

typescript
const text = "Hello, TypeScript World!";

// 長さ
console.log(text.length); // 23

// 検索
console.log(text.includes("TypeScript")); // true
console.log(text.startsWith("Hello"));    // true
console.log(text.endsWith("!"));          // true

// 位置を取得
console.log(text.indexOf("TypeScript"));  // 7
console.log(text.indexOf("Java"));        // -1(見つからない)

変換

typescript
const input = "  Hello World  ";

// 大文字・小文字変換
console.log(input.toUpperCase()); // "  HELLO WORLD  "
console.log(input.toLowerCase()); // "  hello world  "

// 空白除去
console.log(input.trim());       // "Hello World"
console.log(input.trimStart());  // "Hello World  "
console.log(input.trimEnd());    // "  Hello World"

切り出し

typescript
const str = "TypeScript";

// slice(開始, 終了) - 終了は含まない
console.log(str.slice(0, 4));   // "Type"
console.log(str.slice(4));      // "Script"
console.log(str.slice(-6));     // "Script"(末尾から6文字)

// substring(開始, 終了)
console.log(str.substring(0, 4)); // "Type"

split と join

文字列を分割したり結合したりする、最も頻繁に使うメソッドです。

typescript
// split: 文字列 → 配列
const csv = "田中,佐藤,鈴木,高橋";
const names = csv.split(",");
console.log(names); // ["田中", "佐藤", "鈴木", "高橋"]

// join: 配列 → 文字列
const joined = names.join(" / ");
console.log(joined); // "田中 / 佐藤 / 鈴木 / 高橋"

// 実用例: パスの操作
const path = "/users/tanaka/documents/report.pdf";
const parts = path.split("/");
const filename = parts[parts.length - 1]; // "report.pdf"

// 実用例: クエリパラメータの解析
const query = "name=tanaka&age=28&dept=dev";
const params = query.split("&").map((pair) => {
  const [key, value] = pair.split("=");
  return { key, value };
});
// [{ key: "name", value: "tanaka" }, { key: "age", value: "28" }, ...]

replace と replaceAll

typescript
// replace: 最初の一致だけ置換
const text = "apple banana apple cherry";
console.log(text.replace("apple", "orange"));
// "orange banana apple cherry"

// replaceAll: 全ての一致を置換
console.log(text.replaceAll("apple", "orange"));
// "orange banana orange cherry"

// 正規表現を使った置換
const phone = "090-1234-5678";
const cleaned = phone.replace(/-/g, ""); // g フラグで全置換
console.log(cleaned); // "09012345678"

// 実用例: テンプレート処理
function fillTemplate(template: string, data: Record<string, string>): string {
  let result = template;
  for (const [key, value] of Object.entries(data)) {
    result = result.replaceAll(`{{${key}}}`, value);
  }
  return result;
}

const email = fillTemplate(
  "{{name}}様、ご注文番号{{orderId}}を承りました。",
  { name: "田中太郎", orderId: "ORD-2025-001" }
);
// "田中太郎様、ご注文番号ORD-2025-001を承りました。"

正規表現の基本

正規表現(RegExp)はパターンマッチングの強力なツールです。

typescript
// 基本的な正規表現
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

// test: パターンにマッチするか判定
console.log(emailPattern.test("user@example.com"));  // true
console.log(emailPattern.test("invalid-email"));      // false

// match: マッチした部分を取得
const text = "電話番号は 090-1234-5678 です";
const phoneMatch = text.match(/\d{3}-\d{4}-\d{4}/);
console.log(phoneMatch?.[0]); // "090-1234-5678"

// よく使うパターン
const patterns = {
  email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
  phone: /^\d{2,4}-\d{2,4}-\d{4}$/,
  postalCode: /^\d{3}-\d{4}$/,
  url: /^https?:\/\/.+/,
};

// バリデーション関数
function validateEmail(email: string): boolean {
  return patterns.email.test(email);
}

padStart と padEnd

文字列を指定の長さまで埋める関数です。

typescript
// padStart: 先頭を埋める
const num = "42";
console.log(num.padStart(5, "0")); // "00042"

// padEnd: 末尾を埋める
const name = "田中";
console.log(name.padEnd(10, ".")); // "田中........"

// 実用例: 日付のフォーマット
function formatDate(date: Date): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const d = String(date.getDate()).padStart(2, "0");
  return `${y}-${m}-${d}`;
}

console.log(formatDate(new Date(2025, 0, 5))); // "2025-01-05"

// 実用例: テーブル表示
function printRow(name: string, score: number): void {
  console.log(`${name.padEnd(15)} ${String(score).padStart(5)}`);
}

printRow("田中太郎", 85);    // "田中太郎            85"
printRow("佐藤花子", 92);    // "佐藤花子            92"

実践:文字列操作の組み合わせ

typescript
// ユーザー入力の正規化
function normalizeInput(input: string): string {
  return input
    .trim()                          // 前後の空白を除去
    .replace(/\s+/g, " ")           // 連続する空白を1つに
    .toLowerCase();                   // 小文字に統一
}

console.log(normalizeInput("  Hello   World  ")); // "hello world"

// スラッグ生成(URL用の文字列)
function createSlug(title: string): string {
  return title
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, "")    // 英数字・空白・ハイフン以外を除去
    .replace(/\s+/g, "-")        // 空白をハイフンに
    .replace(/-+/g, "-");        // 連続ハイフンを1つに
}

console.log(createSlug("Hello World! This is a Test")); // "hello-world-this-is-a-test"

// CSV行のパース
function parseCsvLine(line: string): string[] {
  return line.split(",").map((field) => field.trim());
}

console.log(parseCsvLine(" name , age , department "));
// ["name", "age", "department"]

まとめ

ポイント内容
テンプレートリテラル`${変数}` で文字列埋め込み
検索includes, startsWith, endsWith, indexOf
変換toUpperCase, toLowerCase, trim
分割・結合split, join
置換replace, replaceAll
正規表現test, match でパターンマッチング
埋め込みpadStart, padEnd

チェックリスト

  • テンプレートリテラルで変数を埋め込める
  • split/join で文字列と配列を変換できる
  • replace/replaceAll で文字列を置換できる
  • 正規表現でバリデーションできる
  • padStart/padEnd で文字列を整形できる

次のステップへ

文字列操作をマスターしました。

次のセクションでは、配列メソッドを学びます。 map, filter, reduce を使いこなせれば、データ処理が一気に効率化します。


推定読了時間: 30分