TypeScriptでの型安全性を高めるために、`unknown`型の適切な使い方を理解することは重要です。本記事では、`unknown`型と`any`型の違いを解説し、実践的な使用方法を紹介します。

unknown型とany型の違い

`unknown`型は TypeScript 3.0で導入された型で、`any`型の型安全な代替として機能します。

// any型の例
let valueAny: any = "Hello";
valueAny.toLowerCase(); // 型チェックなしで実行可能
valueAny = 123;
valueAny.toLowerCase(); // 実行時エラーになる可能性あり

// unknown型の例
let valueUnknown: unknown = "Hello";
valueUnknown.toLowerCase(); // コンパイルエラー

`any`型は型チェックを完全に無効化しますが、`unknown`型は型チェックを強制します。これにより、予期せぬランタイムエラーを防ぐことができます。

unknown型の安全な使用方法

1. 型ガードによる型の絞り込み

function processValue(value: unknown) {
    if (typeof value === "string") {
        // この中ではvalueは文字列として扱える
        return value.toLowerCase();
    }
    if (typeof value === "number") {
        // この中ではvalueは数値として扱える
        return value.toFixed(2);
    }
    throw new Error("Unsupported type");
}

2. 型アサーションの活用

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

const data: unknown = JSON.parse('{"id": 1, "name": "John"}');

// 型アサーションを使用
const user = data as User;

// より安全な方法:型ガードを組み合わせる
function isUser(value: unknown): value is User {
    const v = value as Record<string, unknown>;
    return (
        typeof v === "object" &&
        v !== null &&
        typeof v.id === "number" &&
        typeof v.name === "string"
    );
}

if (isUser(data)) {
    console.log(data.name); // 安全にアクセス可能
}

3. ジェネリクスとの組み合わせ

function safeParseJSON<T>(json: string): T | null {
    try {
        const parsed = JSON.parse(json) as unknown;
        return parsed as T;
    } catch {
        return null;
    }
}

interface Product {
    id: number;
    name: string;
    price: number;
}

const product = safeParseJSON<Product>('{"id": 1, "name": "Product", "price": 100}');

実践的なユースケース

APIレスポンスの型安全な処理

async function fetchData<T>(url: string): Promise<T> {
    const response = await fetch(url);
    const data: unknown = await response.json();
    
    // 型ガードを使用して安全に型を確認
    if (!data || typeof data !== "object") {
        throw new Error("Invalid response data");
    }
    
    return data as T;
}

エラーハンドリング

function handleError(error: unknown) {
    if (error instanceof Error) {
        console.error(error.message);
        return;
    }
    if (typeof error === "string") {
        console.error(error);
        return;
    }
    console.error("An unknown error occurred");
}

まとめ

`unknown`型は、型安全性を損なうことなく柔軟な型定義を可能にする強力な機能です。以下の点を意識することで、より安全なTypeScriptコードを書くことができます:

  • `any`型の代わりに`unknown`型を使用する
  • 型ガードを活用して型を適切に絞り込む
  • 必要に応じて型アサーションを使用する
  • ジェネリクスと組み合わせて型安全性を高める

これらの手法を適切に組み合わせることで、型安全性を保ちながら柔軟なコードを書くことができます。