コピペで使える!TypeScriptユーティリティクラス10選

TypeScriptを導入したプロジェクトでは、よく使う処理をモジュール化しておくと開発効率が一気に高まります。本記事では、DOM操作や日付処理、バリデーション、API通信、ID生成、イベント制御、非同期処理、Cookie・Storageの管理など、さまざまな場面で使える汎用的なユーティリティクラスを紹介します。 すべてのコードはそのままコピペして使える形式で掲載していますが、プロジェクトにあわせて調整したり、他のモジュールと組み合わせて活用することで、より高い柔軟性と再利用性が得られます。チーム開発や業務効率化にも役立つ内容となっています。必要なモジュールだけを自由に組み合わせて、プロジェクトのベース構築にご活用ください。


1. DOM要素操作ユーティリティクラス

DOM操作の基本を網羅したクラスです。クラスの追加・削除・切り替えや、要素の取得を簡潔に行えます。

// modules/DomHelper.ts
export class DomHelper {
    /**
     * 単一のDOM要素を取得(存在しない場合はnullを返さないようにエラー)
     */
    static getElement<T extends Element = HTMLElement>(selector: string): T {
        const element = document.querySelector<T>(selector);
        if (!element) throw new Error(`Element not found: ${selector}`);
        return element;
    }

    /**
     * 複数のDOM要素を取得(NodeListで返す。存在しない場合も空のNodeListを返す。)
     */
    static getElements<T extends Element = HTMLElement>(selector: string): NodeListOf<T> {
        return document.querySelectorAll<T>(selector);
    }

    /**
     * 指定した要素にクラスを追加
     */
    static addClass(element: Element, className: string): void {
        element.classList.add(className);
    }

    /**
     * 指定した要素からクラスを削除
     */
    static removeClass(element: Element, className: string): void {
        element.classList.remove(className);
    }

    /**
     * 指定した要素のクラスをトグル(付け外し)
     */
    static toggleClass(element: Element, className: string): void {
        element.classList.toggle(className);
    }
}

使い方:

import { DomHelper } from '@/modules/DomHelper';

const button: HTMLButtonElement = DomHelper.getElement<HTMLButtonElement>('.js-button');
DomHelper.addClass(button, 'active');
DomHelper.toggleClass(button, 'is-open');

const items: NodeListOf<Element> = DomHelper.getElements('.list-item');
items.forEach(item => {
    DomHelper.addClass(item, 'loaded');
});

2. 日付操作ユーティリティクラス

日付のフォーマット変換をはじめ、年月日の取得や曜日の取得、日付の加算・減算・比較までまとめたクラスです。

// modules/DateUtil.ts
export class DateUtil {
    /**
     * 指定フォーマット(例:YYYY-MM-DD)で日付を文字列に変換
     */
    static format(date: Date, format = 'YYYY-MM-DD'): string {
        const year = date.getFullYear().toString();
        const month = (date.getMonth() + 1).toString().padStart(2, '0');
        const day = date.getDate().toString().padStart(2, '0');

        return format
            .replace('YYYY', year)
            .replace('MM', month)
            .replace('DD', day);
    }

    /**
     * 日付から曜日(日本語)を取得
     */
    static getDayOfWeek(date: Date): string {
        const days = ['日', '月', '火', '水', '木', '金', '土'];
        return days[date.getDay()];
    }

    /**
     * 現在の日付を取得(時刻なし)
     */
    static getToday(): Date {
        const now = new Date();
        return new Date(now.getFullYear(), now.getMonth(), now.getDate());
    }

    /**
     * 指定日数を加算した新しい日付を返す
     */
    static addDays(date: Date, days: number): Date {
        const result = new Date(date);
        result.setDate(result.getDate() + days);
        return result;
    }

    /**
     * 指定日数を減算した新しい日付を返す
     */
    static subtractDays(date: Date, days: number): Date {
        return this.addDays(date, -days);
    }

    /**
     * 2つの日付の差(日数)を計算する(date2 - date1)
     */
    static diffInDays(date1: Date, date2: Date): number {
        const msPerDay = 1000 * 60 * 60 * 24;
        const timeDiff = date2.getTime() - date1.getTime();
        return Math.floor(timeDiff / msPerDay);
    }
}

使い方:

import { DateUtil } from '@/modules/DateUtil';

const today = new Date();
console.log(DateUtil.format(today)); // 2025-05-28
console.log(DateUtil.format(today, 'MM/DD/YYYY')); // 05/28/2025
console.log(DateUtil.getDayOfWeek(today)); // 火(例)

const justDate = DateUtil.getToday();
console.log(justDate); // 2025-05-28T00:00:00.000Z

const nextWeek = DateUtil.addDays(today, 7);
console.log(DateUtil.format(nextWeek)); // 2025-06-04

const lastWeek = DateUtil.subtractDays(today, 7);
console.log(DateUtil.format(lastWeek)); // 2025-05-21

const daysBetween = DateUtil.diffInDays(lastWeek, nextWeek);
console.log(daysBetween); // 14

3. フォーム入力バリデーションユーティリティクラス

メールや電話番号、入力必須など、フロントエンドでよく使うバリデーションをまとめたクラス形式のユーティリティです。

// modules/Validator.ts
export class Validator {
    /** メールアドレス形式か検証 */
    static isValidEmail(email: string): boolean {
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    }

    /** 空でないかを検証 */
    static isNotEmpty(value: string): boolean {
        return value.trim().length > 0;
    }

    /** 数字のみかを検証 */
    static isOnlyNumber(value: string): boolean {
        return /^\d+$/.test(value);
    }

    /** 指定された長さの範囲内かを検証 */
    static isInLengthRange(value: string, min: number, max: number): boolean {
        const length = value.trim().length;
        return length >= min && length <= max;
    }

    /** 電話番号の形式かを検証(10〜11桁の数字) */
    static isValidPhoneNumber(value: string): boolean {
        return /^\d{10,11}$/.test(value.replace(/[-\s]/g, ''));
    }
}

使い方:

import {
    isValidEmail,
    isNotEmpty,
    isOnlyNumber,
    isInLengthRange,
    isValidPhoneNumber
} from '@/modules/Validator';

console.log(isValidEmail('test@example.com')); // true
console.log(isNotEmpty('hello')); // true
console.log(isOnlyNumber('12345')); // true
console.log(isInLengthRange('hello', 3, 10)); // true
console.log(isValidPhoneNumber('090-1234-5678')); // true

4. オブジェクト操作ユーティリティクラス

オブジェクトのディープコピーに加え、キーのフィルタリングやマージなど、オブジェクト操作全般に使える便利なクラスです。

// modules/ObjectUtil.ts
export class ObjectUtil {
    /**
     * オブジェクトのディープコピーを作成
     */
    static deepClone<T>(obj: T): T {
        return JSON.parse(JSON.stringify(obj));
    }

    /**
     * 指定されたキーのみを抽出して新しいオブジェクトを返す
     */
    static pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
        const result = {} as Pick<T, K>;
        keys.forEach(key => {
            if (key in obj) {
                result[key] = obj[key];
            }
        });
        return result;
    }

    /**
     * オブジェクトをマージ(右側のオブジェクトが優先)
     */
    static merge<T extends object, U extends object>(obj1: T, obj2: U): T & U {
        return { ...obj1, ...obj2 };
    }
}

使い方:

import { ObjectUtil } from '@/modules/ObjectUtil';

const original = { name: 'Alice', age: 25 };
const copy = ObjectUtil.deepClone(original);

const picked = ObjectUtil.pick(original, ['name']); // { name: 'Alice' }

const merged = ObjectUtil.merge(original, { age: 30, city: 'Tokyo' }); // { name: 'Alice', age: 30, city: 'Tokyo' }

5. 汎用的なAPIクライアントクラス

REST APIへのGET・POST・PUT・DELETEリクエストを共通化できる便利なクライアントクラスです。

// modules/ApiClient.ts
export class ApiClient {
    constructor(private baseUrl: string) {}

    async get<T>(endpoint: string, params?: Record<string, any>): Promise<T> {
        const url = new URL(`${this.baseUrl}${endpoint}`);
        if (params) {
            Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, String(value)));
        }
        const response = await fetch(url.toString());
        if (!response.ok) throw new Error(response.statusText);
        return await response.json();
    }

    async post<T>(endpoint: string, body: any): Promise<T> {
        const response = await fetch(`${this.baseUrl}${endpoint}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body)
        });
        if (!response.ok) throw new Error(response.statusText);
        return await response.json();
    }

    async put<T>(endpoint: string, body: any): Promise<T> {
        const response = await fetch(`${this.baseUrl}${endpoint}`, {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body)
        });
        if (!response.ok) throw new Error(response.statusText);
        return await response.json();
    }

    async delete<T>(endpoint: string): Promise<T> {
        const response = await fetch(`${this.baseUrl}${endpoint}`, {
            method: 'DELETE'
        });
        if (!response.ok) throw new Error(response.statusText);
        return await response.json();
    }
}

使い方:

import { ApiClient } from '@/modules/ApiClient';

const api = new ApiClient('https://api.example.com');

const [userErr, user] = await api.get('/users/1').then(data => [null, data]).catch(err => [err, null]);
if (userErr) {
    console.error(userErr);
} else {
    console.log(user);
}

const newUser = await api.post('/users', { name: 'Alice' });

6. ランダムなIDやトークンを生成するユーティリティクラス

一意なIDやトークンを生成したいときに役立つユーティリティです。UUID生成にも対応しています。

// modules/IdUtil.ts
export class IdUtil {
    /**
     * 接頭辞付きのランダムなIDを生成(例: id-abc123de)
     */
    static generateRandomId(prefix = 'id'): string {
        return `${prefix}-${Math.random().toString(36).substring(2, 10)}`;
    }

    /**
     * UUID v4 形式の文字列を生成
     */
    static generateUUID(): string {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            const r = Math.random() * 16 | 0;
            const v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    /**
     * 指定した長さのランダムな英数字トークンを生成
     */
    static generateToken(length: number = 32): string {
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        return Array.from(crypto.getRandomValues(new Uint8Array(length)))
            .map(byte => chars.charAt(byte % chars.length))
            .join('');
    }
}

使い方:

import { IdUtil } from '@/modules/IdUtil';

const id = IdUtil.generateRandomId(); // 例: id-x8f3k2lz
const customId = IdUtil.generateRandomId('user'); // 例: user-j3l9p3kq

const uuid = IdUtil.generateUUID(); // 例: 3b12f1df-5232-4e2b-8b2e-56a3ab6e5f2f

const token = IdUtil.generateToken(); // 例: Xkd83jfdla8sDk3021fjLsm02fjQdkdj

7. イベント制御ユーティリティクラス(デバウンス・スロットリング)

高頻度イベントの最適化に使える、定番のデバウンス・スロットリング処理をまとめたクラスです。

// modules/TimingUtil.ts
export class TimingUtil {
    /**
     * デバウンス処理:指定時間後に1度だけ関数を実行
     */
    static debounce<F extends (...args: any[]) => void>(func: F, delay: number): F {
        let timeoutId: ReturnType<typeof setTimeout>;
        return function (this: any, ...args: any[]) {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => func.apply(this, args), delay);
        } as F;
    }

    /**
     * スロットリング処理:一定間隔ごとに関数を実行
     */
    static throttle<F extends (...args: any[]) => void>(func: F, limit: number): F {
        let lastCall = 0;
        return function (this: any, ...args: any[]) {
            const now = Date.now();
            if (now - lastCall >= limit) {
                lastCall = now;
                func.apply(this, args);
            }
        } as F;
    }
}

使い方:

import { TimingUtil } from '@/modules/TimingUtil';

const onResize = TimingUtil.debounce(() => {
    console.log('resize event');
}, 300);

const onScroll = TimingUtil.throttle(() => {
    console.log('scroll event');
}, 200);

window.addEventListener('resize', onResize);
window.addEventListener('scroll', onScroll);

8. 非同期制御ユーティリティクラス(遅延・ポーリング)

待機処理や条件成立までのポーリングなど、非同期フローを制御する便利な関数を提供します。

// modules/AsyncUtil.ts
export class AsyncUtil {
    /**
     * 指定時間後に解決されるPromise(遅延実行に利用)
     */
    static delay(ms: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    /**
     * 条件関数がtrueになるまで定期的にチェックする(ポーリング)
     */
    static async polling(
        checkFn: () => boolean,
        interval = 500,
        timeout = 5000
    ): Promise<void> {
        const start = Date.now();
        return new Promise((resolve, reject) => {
            const check = () => {
                if (checkFn()) return resolve();
                if (Date.now() - start > timeout) return reject(new Error('Polling timeout'));
                setTimeout(check, interval);
            };
            check();
        });
    }
}

使い方:

import { AsyncUtil } from '@/modules/AsyncUtil';

await AsyncUtil.delay(1000); // 1秒後に次の処理へ

await AsyncUtil.polling(() => document.querySelector('#js-loaded') !== null);

9. Cookieの保存・取得・削除ユーティリティ

Cookieを手軽に操作できるユーティリティです。削除や全削除も1行で実行可能です。

// modules/CookieUtil.ts
export const CookieUtil = {
    set(name: string, value: string, days = 7) {
        const date = new Date();
        date.setDate(date.getDate() + days);
        document.cookie = `${name}=${encodeURIComponent(value)}; expires=${date.toUTCString()}; path=/`;
    },
    get(name: string): string | null {
        const match = document.cookie.match(new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)'));
        return match ? decodeURIComponent(match[1]) : null;
    },
    remove(name: string) {
        this.set(name, '', -1);
    },
    clearAll() {
        document.cookie.split(';').forEach(cookie => {
            const eqPos = cookie.indexOf('=');
            const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
            this.remove(name.trim());
        });
    }
};

使い方:

import { CookieUtil } from '@/modules/CookieUtil';

CookieUtil.set('username', 'Alice');
const name = CookieUtil.get('username');
CookieUtil.remove('username');
CookieUtil.clearAll();

10. Storage(localStorage)の保存・取得・削除ユーティリティ

ローカルストレージの読み書きを安全に行えるラッパーです。オブジェクトの保存・取得にも対応します。

// modules/StorageUtil.ts
export const StorageUtil = {
    set(key: string, value: any) {
        localStorage.setItem(key, JSON.stringify(value));
    },
    get<T>(key: string): T | null {
        const item = localStorage.getItem(key);
        return item ? (JSON.parse(item) as T) : null;
    },
    remove(key: string) {
        localStorage.removeItem(key);
    },
    clearAll() {
        localStorage.clear();
    }
};

使い方:

import { StorageUtil } from '@/modules/StorageUtil';

StorageUtil.set('theme', 'dark');
const theme = StorageUtil.get<string>('theme');
StorageUtil.remove('theme');
StorageUtil.clearAll();

まとめ:チーム開発でも役立つTypeScriptユーティリティ

TypeScriptのユーティリティ関数は、型定義の強さとコードの再利用性の高さから、プロジェクトに一つの「共通モジュール」として導入するだけで、バグの抑制や保守性の向上に貢献します。 しかし、利用しているフレームワークやライブラリに同等の機能がある場合、独自にユーティリティクラスを作る必要はありません。例えば、LodashやRamda、date-fnsなどのライブラリは、強力なユーティリティ関数を提供しています。 また、ほんの少しの重複コードのためにユーティリティクラスを作成すると、かえってクラスの数が増え、コードの見通しが悪くなることがあります。
適切な設計と活用によって、クリーンで効率的なコードベースを構築することができます。本記事で紹介したユーティリティクラスをプロジェクトに取り入れ、開発効率とコード品質の両立を目指しましょう。

制作会社・フリーランス開発者の方へ
コードスニペットや共通モジュールの整備など開発環境のセットアップだけでもご相談いただけます。お気軽にご連絡ください!

Contact

ウェブサイトの制作や運用に関わる
お悩みやご相談
お気軽にお問い合わせ下さい

ウェブサイトと一口に言っても、企業サイトやECサイト、ブログ、SNSなど、その“カタチ”は目的に応じてさまざまであり、構築方法や使用する技術も大きく異なります。株式会社コナックスでは、お客様のご要望やブランドの個性を丁寧に汲み取り、最適なウェブサイトの“カタチ”をご提案いたします。

デザイン、ユーザビリティ、SEO対策はもちろん、コンテンツ制作やマーケティング戦略に至るまで、あらゆるフェーズでお客様のビジネスに寄り添い、成果につながるウェブサイトづくりをサポートいたします。私たちは、ウェブサイトの公開をゴールではなくスタートと捉え、お客様のビジネスの成功に向けて共に伴走してまいります。