TypeScriptチートシート

中級 | 15分 で読める | 2025.01.10

公式ドキュメント

概要

TypeScript は JavaScript に静的型付けを加える言語です。このチートシートでは、基本型、ユニオン型、ジェネリクス、ユーティリティ型、型ガード、条件型、Mapped Types を、実装時に確認しやすい順でまとめます。

最初に覚える最小セット

項目まず使う型
基本型string / number / boolean
配列string[] / Array<string>
オブジェクトtype User = { ... }
ユニオン`“pending"
Optionalname?: string
ジェネリクスfunction fn<T>(value: T): T
安全な不明値unknown
型絞り込みtypeof / instanceof / in

TypeScript は型で実行時エラーを完全に防ぐものではありません。外部入力は unknown として受け取り、型ガードやバリデーションで絞り込んでから使います。

基本的な型

// プリミティブ型
const name: string = "Alice";
const age: number = 25;
const isActive: boolean = true;
const id: bigint = 100n;
const symbol: symbol = Symbol("id");

// 配列
const numbers: number[] = [1, 2, 3];
const names: Array<string> = ["Alice", "Bob"];

// タプル
const tuple: [string, number] = ["Alice", 25];
const namedTuple: [name: string, age: number] = ["Alice", 25];

// オブジェクト
const user: { name: string; age: number } = { name: "Alice", age: 25 };

// any, unknown, never
let anyValue: any = "anything";
let unknownValue: unknown = "must check type";
function throwError(): never {
 throw new Error("error");
}

型エイリアスとインターフェース

// 型エイリアス
type User = {
 id: string;
 name: string;
 email: string;
};

type ID = string | number;

// インターフェース
interface Product {
 id: string;
 name: string;
 price: number;
}

// 拡張
interface AdminUser extends User {
 role: "admin";
 permissions: string[];
}

type ExtendedProduct = Product & {
 category: string;
};

ポイント: typeはユニオンやプリミティブの別名に、interfaceはオブジェクト型の定義に使い分けるのが一般的。interfaceはextendsで拡張、typeは&で合成します。

ユニオン型とインターセクション型

// ユニオン型(いずれか)
type Status = "pending" | "approved" | "rejected";
type StringOrNumber = string | number;

// インターセクション型(両方)
type Employee = User & { department: string };

// 判別可能なユニオン
type Result<T> =
 | { success: true; data: T }
 | { success: false; error: string };

function handleResult(result: Result<string>) {
 if (result.success) {
 console.log(result.data); // string
 } else {
 console.log(result.error); // string
 }
}

ジェネリクス

// 関数
function identity<T>(value: T): T {
 return value;
}

// 複数の型パラメータ
function pair<T, U>(first: T, second: U): [T, U] {
 return [first, second];
}

// 制約付きジェネリクス
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
 return obj[key];
}

// インターフェース
interface ApiResponse<T> {
 data: T;
 status: number;
 message: string;
}

// クラス
class Container<T> {
 private value: T;

 constructor(value: T) {
 this.value = value;
 }

 getValue(): T {
 return this.value;
 }
}

実践メモ: 判別可能なユニオン(Discriminated Union)はエラーハンドリングやAPIレスポンスの型定義に最適。共通のリテラルフィールド(success: true/false等)でTypeScriptが自動的に型を絞り込みます。

ユーティリティ型

interface User {
 id: string;
 name: string;
 email: string;
 age?: number;
}

// Partial - 全てオプショナルに
type PartialUser = Partial<User>;
// { id?: string; name?: string; email?: string; age?: number; }

// Required - 全て必須に
type RequiredUser = Required<User>;

// Readonly - 読み取り専用に
type ReadonlyUser = Readonly<User>;

// Pick - 特定のプロパティのみ
type UserName = Pick<User, "id" | "name">;
// { id: string; name: string; }

// Omit - 特定のプロパティを除外
type UserWithoutEmail = Omit<User, "email">;

// Record - キーと値の型を指定
type UserRecord = Record<string, User>;

// Exclude - ユニオンから除外
type Status = "pending" | "approved" | "rejected";
type ActiveStatus = Exclude<Status, "rejected">;
// "pending" | "approved"

// Extract - ユニオンから抽出
type ExtractedStatus = Extract<Status, "pending" | "approved">;

// NonNullable - nullとundefinedを除外
type NonNullableString = NonNullable<string | null | undefined>;

// ReturnType - 関数の戻り値の型
function getUser() {
 return { id: "1", name: "Alice" };
}
type UserReturn = ReturnType<typeof getUser>;

// Parameters - 関数のパラメータの型
type GetUserParams = Parameters<typeof getUser>;

ポイント: Partial(全てオプショナル)、Pick(一部だけ)、Omit(一部を除外)の3つは頻出。既存の型から新しい型を簡潔に導出できます。

注意: anyは型チェックを完全に無効化します。unknownを使えば、利用前に型チェックが強制されるので安全ですanyの使用は最小限にしましょう。

型ガード

// typeof
function process(value: string | number) {
 if (typeof value === "string") {
 return value.toUpperCase();
 }
 return value * 2;
}

// instanceof
function handleError(error: Error | string) {
 if (error instanceof Error) {
 return error.message;
 }
 return error;
}

// in演算子
interface Dog {
 bark(): void;
}
interface Cat {
 meow(): void;
}

function speak(animal: Dog | Cat) {
 if ("bark" in animal) {
 animal.bark();
 } else {
 animal.meow();
 }
}

// カスタム型ガード
function isUser(value: unknown): value is User {
 return (
 typeof value === "object" &&
 value !== null &&
 "id" in value &&
 "name" in value
 );
}

条件型

// 基本
type IsString<T> = T extends string ? true : false;

// infer
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Result = UnwrapPromise<Promise<string>>; // string

// 配列の要素型
type ArrayElement<T> = T extends (infer U)[] ? U : never;
type Item = ArrayElement<string[]>; // string

// 関数の戻り値
type ReturnOf<T> = T extends (...args: any[]) => infer R ? R : never;

Mapped Types

// 基本
type Nullable<T> = {
 [K in keyof T]: T[K] | null;
};

// 修飾子の操作
type Mutable<T> = {
 -readonly [K in keyof T]: T[K];
};

type OptionalToRequired<T> = {
 [K in keyof T]-?: T[K];
};

// キーの変換
type Getters<T> = {
 [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

type UserGetters = Getters<User>;
// { getId: () => string; getName: () => string; ... }

テンプレートリテラル型

構文説明
type ApiRoute = `${HttpMethod} ${Endpoint}`;ユニオン型同士を組み合わせて “GET /users” | “GET /products” | … を生成
type UpperCase = Uppercase<"hello">;”HELLO” に変換
type LowerCase = Lowercase<"HELLO">;”hello” に変換
type Capitalize = Capitalize<"hello">;”Hello” に変換
type Uncapitalize = Uncapitalize<"Hello">;”hello” に変換

よくあるパターン

// nullable型
type Nullable<T> = T | null;
type Optional<T> = T | undefined;
type Maybe<T> = T | null | undefined;

// Result型
type Result<T, E = Error> =
 | { ok: true; value: T }
 | { ok: false; error: E };

// 再帰型
type DeepPartial<T> = {
 [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};

// 読み取り専用配列
type ReadonlyArray<T> = readonly T[];

// 非同期関数の戻り値
type AsyncReturnType<T extends (...args: any) => Promise<any>> =
 T extends (...args: any) => Promise<infer R> ? R : never;

実践メモ: as constで配列やオブジェクトをリテラル型に変換すると、typeofと組み合わせてユニオン型を自動生成できます。定数からの型導出に最適です。

注意: 型アサーション(as Type)は型チェックを無視するため、実行時エラーの原因になります。型ガード(typeof/instanceof/in)で安全に型を絞り込みましょう。

実用Tips

構文説明
const colors = ["red", "green", "blue"] as const; type Color = typeof colors[number];as const でリテラル型に変換。配列から “red” | “green” | “blue” 型を自動生成
const config = {...} satisfies Record<string, string | number>;satisfies で型チェックしつつ推論を維持
const statusMap = { pending: "保留中", ... } as const; type Status = keyof typeof statusMap;オブジェクトから “pending” | “approved” | “rejected” のユニオン型を自動導出

まとめ

TypeScript では、any を増やすより、unknown、型ガード、判別可能なユニオン、ユーティリティ型を使って安全に型を狭めることが重要です。as に頼りすぎると型チェックをすり抜けるため、実行時データは検証してから扱います。

型システムの細かい挙動は TypeScript のバージョンで変わる場合があります。詳細は公式ハンドブックと Playground で確認してください。

参考リソース

関連記事

← 一覧に戻る
PR
PR
PR
PR