型の種類
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
// プロパティの存在で型を判定