さとまたwiki

型の種類

TypeScriptで使える様々な型を学ぶ

プリミティブ型(基本の型)

日常での例え:基本の材料

料理で言うと、塩・砂糖・小麦粉のような「基本の材料」

これらを組み合わせて複雑な料理(型)を作ります

基本の型

string, number, boolean

typescript
// 文字列型
let name: string = "田中";
let greeting: string = `こんにちは、${name}さん`;

// 数値型(整数も小数も同じnumber)
let age: number = 25;
let price: number = 1980.5;
let hex: number = 0xff;  // 16進数もOK

// 真偽値型
let isActive: boolean = true;
let isLoggedIn: boolean = false;

// これらは「プリミティブ型」と呼ばれる
// 最も基本的な型です
プレビュー
string → 文字列
number → 数値
boolean → true/false

null と undefined

「値がない」を表す型

typescript
// undefined: 値が設定されていない
let notSet: undefined = undefined;

// null: 意図的に「空」を設定
let empty: null = null;

// 実際の使い方(Union型と組み合わせ)
let username: string | null = null;  // まだ設定されていない
username = "田中";  // 後から設定

// undefinedは「まだない」
// nullは「意図的に空」という違いがある
プレビュー
// undefined = 未定義
// null = 意図的な空

配列型(Array)

日常での例え:同じ種類の物を入れる棚

「本棚」には本だけ、「靴箱」には靴だけ

配列型も「この棚には〇〇型だけ」と決められます

配列の型指定

2つの書き方がある

typescript
// 書き方1: 型[]
let numbers: number[] = [1, 2, 3, 4, 5];
let names: string[] = ["田中", "鈴木", "佐藤"];

// 書き方2: Array<型>
let scores: Array<number> = [85, 90, 78];
let items: Array<string> = ["りんご", "みかん"];

// 両方同じ意味!好きな方を使ってOK

// 配列に違う型を入れようとするとエラー
numbers.push("六");  // ❌ エラー!
names.push(123);     // ❌ エラー!
プレビュー
number[] = Array<number>
// どちらも同じ意味

複合型の配列

オブジェクトの配列など

typescript
// オブジェクトの配列
let users: { name: string; age: number }[] = [
  { name: "田中", age: 25 },
  { name: "鈴木", age: 30 }
];

// 複数の型を許容する配列
let mixed: (string | number)[] = [1, "two", 3, "four"];

// 読み取り専用の配列
const colors: readonly string[] = ["red", "green", "blue"];
colors.push("yellow");  // ❌ エラー!変更できない
プレビュー
// readonly = 変更禁止
// 安全性が上がる

タプル型(Tuple)

日常での例え:決まった順番の書類セット

「申請書セット」= 1枚目が申請書、2枚目が身分証明書、3枚目が写真

順番と種類が決まっている配列がタプルです

タプルの基本

要素の順番と型が固定

typescript
// タプル: [型1, 型2, 型3, ...]
let person: [string, number] = ["田中", 25];

// 順番が大事!
person = [25, "田中"];  // ❌ エラー!順番が違う

// 要素へのアクセス
const name = person[0];  // string型
const age = person[1];   // number型

// 実用例: 座標
let point: [number, number] = [10, 20];

// 実用例: キーと値のペア
let entry: [string, number] = ["price", 1000];
プレビュー
[string, number]
// 1番目は文字列、2番目は数値

オブジェクト型

日常での例え:項目が決まった申込書

申込書には「名前欄」「住所欄」「電話番号欄」が決まっている

オブジェクト型も「このプロパティが必要」と決められます

オブジェクト型の定義

プロパティの型を指定

typescript
// インラインでオブジェクト型を定義
let user: {
  name: string;
  age: number;
  email: string;
} = {
  name: "田中太郎",
  age: 25,
  email: "tanaka@example.com"
};

// 存在しないプロパティはエラー
user.address;  // ❌ エラー: 'address'は存在しない

// 必須プロパティが足りないとエラー
let badUser: { name: string; age: number } = {
  name: "鈴木"
  // ❌ エラー: 'age'が必要
};
プレビュー
// オブジェクトの形を定義
// 足りない・余分はエラー

オプショナルと読み取り専用

? と readonly

typescript
let product: {
  id: number;
  name: string;
  description?: string;  // ? = オプショナル(省略可能)
  readonly price: number;  // readonly = 変更禁止
} = {
  id: 1,
  name: "ノートPC",
  price: 98000
  // descriptionは省略OK
};

// オプショナルプロパティは後から追加OK
product.description = "軽量で高性能";

// readonlyは変更できない
product.price = 88000;  // ❌ エラー!
プレビュー
? = オプショナル
readonly = 変更禁止

列挙型(Enum)

日常での例え:選択肢が決まっているアンケート

「満足度」→ 「とても満足」「満足」「普通」「不満」から選ぶ

Enumは選択肢を名前付きで定義できます

Enumの基本

選択肢を定義

typescript
// 数値Enum(デフォルト)
enum Direction {
  Up,     // 0
  Down,   // 1
  Left,   // 2
  Right   // 3
}

let move: Direction = Direction.Up;

// 文字列Enum(こちらがおすすめ)
enum Status {
  Pending = "pending",
  Approved = "approved",
  Rejected = "rejected"
}

let orderStatus: Status = Status.Pending;
console.log(orderStatus);  // "pending"

// 型安全!存在しない値はエラー
orderStatus = "unknown";  // ❌ エラー!
プレビュー
enum Status {
Pending = "pending"
}

Enumの代わりにUnion型も使える

最近は type Status = "pending" | "approved" | "rejected" のように

Union型で書くことも多いです。こちらの方がシンプル!

特殊な型

any型

なんでもOK(非推奨)

typescript
// any: どんな型でもOK
let anything: any = "hello";
anything = 123;      // OK
anything = true;     // OK
anything = { x: 1 }; // OK

// anyは型チェックを無効化する
// TypeScriptの恩恵がなくなるので避けるべき!

// どうしても型がわからない時だけ使う
// JSONパースの結果など
プレビュー
⚠️ anyは最終手段!
型安全性が失われる

unknown型

安全な「なんでもOK」

typescript
// unknown: 何が来るかわからない
let input: unknown = getUserInput();

// unknownはそのままでは使えない
input.toUpperCase();  // ❌ エラー!

// 型チェックしてから使う
if (typeof input === "string") {
  input.toUpperCase();  // ✅ OK!
}

// anyより安全!
// 「何かわからないけど、確認してから使う」
プレビュー
unknown = anyの安全版
// 使う前に型チェック必須

never型

絶対に起きない

typescript
// never: 決して返らない関数
function throwError(message: string): never {
  throw new Error(message);
  // ここには到達しない
}

// 無限ループ
function infiniteLoop(): never {
  while (true) {
    // 永遠に終わらない
  }
}

// 型の絞り込みで残らない場合
type Shape = "circle" | "square";

function getArea(shape: Shape) {
  switch (shape) {
    case "circle": return /* ... */;
    case "square": return /* ... */;
    default:
      // ここに来たら never 型
      const _exhaustive: never = shape;
  }
}
プレビュー
never = 絶対に発生しない
// エラーや無限ループなど

型の絞り込み(Type Narrowing)

日常での例え:荷物の仕分け

「この荷物は壊れ物?」→ はい → 丁寧に扱う

条件分岐で型を特定し、適切な処理をします

typeofで絞り込み

プリミティブ型の判定

typescript
function printValue(value: string | number) {
  // ここではvalueはstring | number

  if (typeof value === "string") {
    // ここではvalueはstring
    console.log(value.toUpperCase());
  } else {
    // ここではvalueはnumber
    console.log(value.toFixed(2));
  }
}

printValue("hello");  // HELLO
printValue(3.14159);  // 3.14
プレビュー
// typeof で型を判定
// TypeScriptが自動で型を絞る

inで絞り込み

プロパティの存在チェック

typescript
type Bird = { fly: () => void };
type Fish = { swim: () => void };

function move(animal: Bird | Fish) {
  if ("fly" in animal) {
    // animalはBird
    animal.fly();
  } else {
    // animalはFish
    animal.swim();
  }
}

// "fly"プロパティがあるか?で判定
プレビュー
"property" in object
// プロパティの存在で型を判定