TypeScript チートシート

型安全なJavaScript開発のためのクイックリファレンス

TypeScriptとは?

TypeScriptは、JavaScriptに静的型付けを追加したプログラミング言語です。 コンパイル時に型エラーを検出することで、実行前にバグを発見し、大規模なアプリケーション開発を安全かつ効率的に進めることができます。

型安全 JavaScriptスーパーセット エディタ補完強化

基本的な型

プリミティブ型は変数宣言時に型注釈で指定

// プリミティブ型
let age: number = 25;
let name: string = "太郎";
let isActive: boolean = true;

// 配列
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["太郎", "花子"];

// タプル
let user: [string, number] = ["太郎", 25];

// any (型安全を失うため非推奨)
let data: any = "文字列でも数値でもOK";

// unknown (anyより安全)
let value: unknown = "型チェック必須";
if (typeof value === "string") {
    console.log(value.toUpperCase());
}

インターフェース

// 基本的なインターフェース
interface User {
    id: number;
    name: string;
    email: string;
}

const user: User = {
    id: 1,
    name: "太郎",
    email: "taro@example.com"
};

// オプショナルプロパティ
interface Product {
    id: number;
    name: string;
    price: number;
    description?: string;  // 省略可能
}

// 読み取り専用プロパティ
interface Config {
    readonly apiKey: string;
    readonly endpoint: string;
}

const config: Config = {
    apiKey: "abc123",
    endpoint: "https://api.example.com"
};
// config.apiKey = "xyz"; // エラー!

型エイリアス

// プリミティブのエイリアス
type ID = number;
type Email = string;

// オブジェクト型
type User = {
    id: ID;
    email: Email;
    createdAt: Date;
};

// ユニオン型
type Status = "pending" | "approved" | "rejected";
type Result = string | number | boolean;

// 関数型
type Callback = (data: string) => void;
type Calculator = (a: number, b: number) => number;

const add: Calculator = (a, b) => a + b;

インターフェースと似ているが、ユニオン型などに使える

プリミティブや関数の型定義に便利

ユニオン型と型ガード

// ユニオン型
type Response = string | number | null;

function handleResponse(res: Response) {
    // 型ガード (typeof)
    if (typeof res === "string") {
        console.log(res.toUpperCase());
    } else if (typeof res === "number") {
        console.log(res.toFixed(2));
    } else {
        console.log("null response");
    }
}

// in演算子による型ガード
type Cat = { meow: () => void };
type Dog = { bark: () => void };

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

// カスタム型ガード
function isString(value: unknown): value is string {
    return typeof value === "string";
}

関数の型

// 基本的な関数
function greet(name: string): string {
    return `Hello, ${name}!`;
}

// オプション引数
function buildName(firstName: string, lastName?: string): string {
    return lastName ? `${firstName} ${lastName}` : firstName;
}

// デフォルト引数
function multiply(a: number, b: number = 1): number {
    return a * b;
}

// Rest引数
function sum(...numbers: number[]): number {
    return numbers.reduce((a, b) => a + b, 0);
}

// アロー関数
const divide = (a: number, b: number): number => a / b;

// void型 (返り値なし)
function logMessage(message: string): void {
    console.log(message);
}

// never型 (決して返らない)
function throwError(message: string): never {
    throw new Error(message);
}

ジェネリクス

型を引数として受け取り、汎用的な処理を実現

// 基本的なジェネリクス関数
function identity<T>(arg: T): T {
    return arg;
}

const result1 = identity<string>("hello");
const result2 = identity<number>(42);

// ジェネリクス配列
function getFirstElement<T>(arr: T[]): T | undefined {
    return arr[0];
}

// ジェネリクスインターフェース
interface Box<T> {
    value: T;
}

const stringBox: Box<string> = { value: "hello" };
const numberBox: Box<number> = { value: 123 };

// 複数の型パラメータ
function pair<K, V>(key: K, value: V): [K, V] {
    return [key, value];
}

const userPair = pair("id", 1);  // [string, number]

// ジェネリクス制約
interface HasLength {
    length: number;
}

function logLength<T extends HasLength>(arg: T): void {
    console.log(arg.length);
}

logLength("hello");     // OK
logLength([1, 2, 3]);   // OK
// logLength(123);      // エラー!

クラス

class Person {
    // プロパティ
    private name: string;
    protected age: number;
    public email: string;

    // コンストラクタ
    constructor(name: string, age: number, email: string) {
        this.name = name;
        this.age = age;
        this.email = email;
    }

    // メソッド
    greet(): string {
        return `Hello, I'm ${this.name}`;
    }

    // Getter
    get fullInfo(): string {
        return `${this.name} (${this.age})`;
    }

    // Setter
    set updateAge(newAge: number) {
        if (newAge > 0) {
            this.age = newAge;
        }
    }
}

// 継承
class Employee extends Person {
    private department: string;

    constructor(name: string, age: number, email: string, dept: string) {
        super(name, age, email);
        this.department = dept;
    }

    getDepartment(): string {
        return this.department;
    }
}

// 抽象クラス
abstract class Animal {
    abstract makeSound(): void;

    move(): void {
        console.log("Moving...");
    }
}

ユーティリティ型

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

// Partial - すべてのプロパティをオプションに
type PartialUser = Partial<User>;
// { id?: number; name?: string; ... }

// Required - すべてのプロパティを必須に
type RequiredUser = Required<PartialUser>;

// Readonly - すべてのプロパティを読み取り専用に
type ReadonlyUser = Readonly<User>;

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

// Omit - 特定のプロパティを除外
type UserWithoutEmail = Omit<User, "email">;
// { id: number; name: string; age: number; }

// Record - キーと値の型を指定
type UserRoles = Record<string, string>;
const roles: UserRoles = {
    admin: "管理者",
    user: "一般ユーザー"
};

// ReturnType - 関数の戻り値の型を取得
function getUser() {
    return { id: 1, name: "太郎" };
}
type UserReturn = ReturnType<typeof getUser>;
// { id: number; name: string; }

非同期処理の型定義

Promise

// Promise型
function fetchUser(id: number): Promise<User> {
    return fetch(`/api/users/${id}`)
        .then(res => res.json());
}

// 使用例
fetchUser(1).then((user: User) => {
    console.log(user.name);
});

async/await

// async関数
async function getUser(id: number): Promise<User> {
    const response = await fetch(`/api/users/${id}`);
    const user: User = await response.json();
    return user;
}

// エラーハンドリング
async function safeGetUser(id: number): Promise<User | null> {
    try {
        return await getUser(id);
    } catch (error) {
        console.error(error);
        return null;
    }
}

実務で役立つTips

厳格モード

tsconfig.jsonで"strict": trueを設定し、型チェックを最大限活用しましょう。

anyを避ける

anyは型安全性を失うため、unknownやジェネリクスを使いましょう。

型推論を活用

明示的な型注釈が不要な場合は、TypeScriptの型推論に任せることでコードを簡潔に保てます。

型ガード活用

ユニオン型を扱う際は、型ガードで型を絞り込み、安全にアクセスしましょう。

tsconfig.json 基本設定

{
  "compilerOptions": {
    "target": "ES2020",                // コンパイル先のJavaScriptバージョン
    "module": "ESNext",                // モジュールシステム
    "lib": ["ES2020", "DOM"],          // 利用可能なライブラリ
    "outDir": "./dist",                // 出力ディレクトリ
    "rootDir": "./src",                // ソースディレクトリ
    "strict": true,                    // 厳格な型チェック有効化
    "esModuleInterop": true,           // CommonJSとESモジュールの互換性
    "skipLibCheck": true,              // 型定義ファイルのチェックスキップ
    "forceConsistentCasingInFileNames": true,  // ファイル名の大文字小文字を厳格にチェック
    "resolveJsonModule": true,         // JSONファイルのインポートを許可
    "moduleResolution": "node",        // Node.js形式のモジュール解決
    "declaration": true,               // .d.tsファイルを生成
    "sourceMap": true                  // ソースマップを生成
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

strict

すべての厳格な型チェックを有効化

target

コンパイル後のJSバージョン

module

モジュールシステム指定

よく使うパターン

APIレスポンスの型定義

interface ApiResponse<T> {
    data: T;
    status: number;
    message?: string;
}

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

async function fetchUser(id: number): Promise<ApiResponse<User>> {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
}

// 使用例
const result = await fetchUser(1);
console.log(result.data.name);  // 型安全!

Enum (列挙型)

// 数値Enum
enum Direction {
    Up,      // 0
    Down,    // 1
    Left,    // 2
    Right    // 3
}

// 文字列Enum (推奨)
enum Status {
    Pending = "PENDING",
    Approved = "APPROVED",
    Rejected = "REJECTED"
}

function updateStatus(status: Status) {
    if (status === Status.Approved) {
        console.log("承認されました");
    }
}

// const enum (コンパイル後にインライン化)
const enum Color {
    Red = "RED",
    Green = "GREEN",
    Blue = "BLUE"
}

型アサーション

// as構文 (推奨)
const input = document.getElementById("name") as HTMLInputElement;
input.value = "太郎";

// 山括弧構文 (JSXでは使えない)
const input2 = <HTMLInputElement>document.getElementById("email");

// 非nullアサーション演算子 (!)
const element = document.getElementById("app")!;  // nullでないと確信

// constアサーション
const config = {
    apiUrl: "https://api.example.com",
    timeout: 5000
} as const;
// config.apiUrl = "...";  // エラー! 読み取り専用

交差型 (Intersection)

interface Person {
    name: string;
    age: number;
}

interface Employee {
    employeeId: number;
    department: string;
}

// 複数の型を結合
type EmployeePerson = Person & Employee;

const emp: EmployeePerson = {
    name: "太郎",
    age: 30,
    employeeId: 1001,
    department: "開発部"
};

コンパイルと実行

1 tsc --init
2 tsc
3 node dist/index.js

よく使うコマンド

# TypeScriptインストール
npm install -g typescript

# tsconfig.json生成
tsc --init

# 単一ファイルコンパイル
tsc index.ts

# プロジェクト全体コンパイル
tsc

# ウォッチモード (変更を監視)
tsc --watch

# バージョン確認
tsc --version

ts-nodeで直接実行

# ts-nodeインストール
npm install -g ts-node

# 直接実行 (コンパイル不要)
ts-node src/index.ts

# Node.jsプロジェクトの場合
npm install --save-dev typescript ts-node @types/node

# package.jsonのscripts
{
  "scripts": {
    "dev": "ts-node src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  }
}