TypeScriptで非同期処理を扱う際の型設計について、実践的なベストプラクティスを解説します。
Promiseを使った基本的な型付け
非同期処理の戻り値の型は、`Promise
// 基本的なPromiseの型定義
function fetchUser(): Promise<User> {
return fetch('/api/user')
.then(response => response.json());
}
// インターフェースの定義
interface User {
id: number;
name: string;
email: string;
}async/awaitを使った型付け
async/awaitを使用する場合も、戻り値の型は`Promise
async function getUserData(): Promise<User> {
const response = await fetch('/api/user');
const user = await response.json();
return user;
}エラーハンドリングの型設計
エラーハンドリングを考慮した型設計は以下のように行います。
// カスタムエラーの定義
class APIError extends Error {
constructor(public statusCode: number, message: string) {
super(message);
this.name = 'APIError';
}
}
// エラーハンドリングを含む非同期関数
async function fetchUserWithError(): Promise<User> {
try {
const response = await fetch('/api/user');
if (!response.ok) {
throw new APIError(response.status, 'Failed to fetch user');
}
return await response.json();
} catch (error) {
if (error instanceof APIError) {
// 型付けされたエラー処理
console.error(`API Error: ${error.statusCode}`);
}
throw error;
}
}ジェネリック型を活用した汎用的な型設計
再利用可能な非同期関数の型設計には、ジェネリック型が有効です。
// 汎用的なAPI呼び出し関数
async function apiRequest<T>(url: string): Promise<T> {
const response = await fetch(url);
if (!response.ok) {
throw new APIError(response.status, 'API request failed');
}
return response.json();
}
// 使用例
const user = await apiRequest<User>('/api/user');
const posts = await apiRequest<Post[]>('/api/posts');非同期関数の戻り値の型推論
TypeScriptの型推論を活用することで、より簡潔なコードを書くことができます。
// 型推論を活用した例
const fetchUserData = async () => {
const response = await fetch('/api/user');
return response.json() as Promise<User>;
};
// 型アサーションを使用した例
const fetchPosts = async () => {
const response = await fetch('/api/posts');
const data = await response.json();
return data as Post[];
};Union型を使った結果の型設計
成功と失敗のケースを明示的に型付けする場合は、Union型が有効です。
interface Success<T> {
success: true;
data: T;
}
interface Failure {
success: false;
error: string;
}
type Result<T> = Success<T> | Failure;
async function fetchData<T>(url: string): Promise<Result<T>> {
try {
const response = await fetch(url);
const data = await response.json();
return { success: true, data };
} catch {
return { success: false, error: 'Failed to fetch data' };
}
}以上の型設計パターンを適切に組み合わせることで、型安全で保守性の高い非同期処理を実装できます。実際のプロジェクトでは、要件に応じて最適な型設計を選択することが重要です。
これらの型設計パターンは、TypeScriptの型システムを最大限に活用し、開発時のエラーを早期に発見できるようにします。また、IDEのコード補完機能も効果的に機能し、開発効率の向上にも繋がります。