

# TypeScript の Lambda 関数ハンドラーの定義
<a name="typescript-handler"></a>

Lambda 関数*ハンドラー*は、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

このページでは、プロジェクトのセットアップオプション、命名規則、ベストプラクティスなど、TypeScript で Lambda 関数ハンドラーを使用する方法について説明します。このページには、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon Simple Storage Service (Amazon S3) バケットに配置する TypeScript Lambda 関数の例も含まれています。関数を書き込んだ後にデプロイする方法については、「[.zip ファイルアーカイブを使用して、トランスパイルされた TypeScript コードを Lambda にデプロイする](typescript-package.md)」または「[コンテナイメージを使用して、トランスパイルされた TypeScript コードを Lambda にデプロイする](typescript-image.md)」を参照してください。

**Topics**
+ [

## TypeScript プロジェクトのセットアップ
](#typescript-handler-setup)
+ [

## TypeScript Lambda 関数コードの例
](#typescript-example-code)
+ [

## CommonJS および ES モジュール
](#typescript-commonjs-es-modules)
+ [

## Node.js の初期化
](#typescript-initialization)
+ [

## ハンドラーの命名規則
](#typescript-handler-naming)
+ [

## 入力イベントオブジェクトの定義とアクセス
](#typescript-example-input)
+ [

## TypeScript 関数の有効なハンドラーパターン
](#typescript-handler-signatures)
+ [

## ハンドラーでの SDK for JavaScript v3 の使用
](#typescript-example-sdk-usage)
+ [

## 環境変数にアクセスする
](#typescript-example-envvars)
+ [

## グローバルな状態を使用する
](#typescript-handler-state)
+ [

## TypeScript Lambda 関数のコードのベストプラクティス
](#typescript-best-practices)

## TypeScript プロジェクトのセットアップ
<a name="typescript-handler-setup"></a>

TypeScript 関数のコードを記述するには、ローカルの統合開発環境 (IDE) またはテキストエディタを使用します。Lambda コンソールでは TypeScript コードを作成できません。

TypeScript Lambda プロジェクトを初期化する方法は複数あります。例えば、`npm` を使用してプロジェクト、[AWS SAM アプリケーション](typescript-package.md#aws-sam-ts)、[AWS CDK アプリケーション](typescript-package.md#aws-cdk-ts)などを作成できます。`npm` を使用してプロジェクトを作成するには:

```
npm init
```

関数コードは `.ts` ファイル内にあり、ビルド時に JavaScript ファイルにトランスパイルします。[esbuild](https://esbuild.github.io/) または Microsoft の TypeScript コンパイラ (`tsc`) を使用して、TypeScript コードを JavaScript にトランスパイルできます。esbuild を使用するには、開発の依存関係として追加します。

```
npm install -D esbuild
```

一般的な TypeScript Lambda 関数プロジェクトは、次の一般的な構造に従います。

```
/project-root
  ├── index.ts - Contains main handler
  ├── dist/ - Contains compiled JavaScript
  ├── package.json - Project metadata and dependencies
  ├── package-lock.json - Dependency lock file
  ├── tsconfig.json - TypeScript configuration
  └── node_modules/ - Installed dependencies
```

## TypeScript Lambda 関数コードの例
<a name="typescript-example-code"></a>

以下の Lambda 関数コードの例では、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon S3 バケットに配置します。この例では、カスタムイベントタイプ (`OrderEvent`) を定義します。AWS イベントソースのタイプ定義をインポートする方法については、「[Lambda のタイプ定義](lambda-typescript.md#typescript-type-definitions)」を参照してください。

**注記**  
この例では、ES モジュールハンドラーを使用します。Lambda は、ES モジュールと CommonJS ハンドラーの両方をサポートしています。詳細については、「[CommonJS および ES モジュール](nodejs-handler.md#nodejs-commonjs-es-modules)」を参照してください。

**Example index.ts Lambda 関数**  

```
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

// Initialize the S3 client outside the handler for reuse
const s3Client = new S3Client();

// Define the shape of the input event
type OrderEvent = {
    order_id: string;
    amount: number;
    item: string;
}

/**
 * Lambda handler for processing orders and storing receipts in S3.
 */
export const handler = async (event: OrderEvent): Promise<string> => {
    try {
        // Access environment variables
        const bucketName = process.env.RECEIPT_BUCKET;
        if (!bucketName) {
            throw new Error('RECEIPT_BUCKET environment variable is not set');
        }

        // Create the receipt content and key destination
        const receiptContent = `OrderID: ${event.order_id}\nAmount: $${event.amount.toFixed(2)}\nItem: ${event.item}`;
        const key = `receipts/${event.order_id}.txt`;

        // Upload the receipt to S3
        await uploadReceiptToS3(bucketName, key, receiptContent);

        console.log(`Successfully processed order ${event.order_id} and stored receipt in S3 bucket ${bucketName}`);
        return 'Success';
    } catch (error) {
        console.error(`Failed to process order: ${error instanceof Error ? error.message : 'Unknown error'}`);
        throw error;
    }
};

/**
 * Helper function to upload receipt to S3
 */
async function uploadReceiptToS3(bucketName: string, key: string, receiptContent: string): Promise<void> {
    try {
        const command = new PutObjectCommand({
            Bucket: bucketName,
            Key: key,
            Body: receiptContent
        });

        await s3Client.send(command);
    } catch (error) {
        throw new Error(`Failed to upload receipt to S3: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
}
```

この `index.ts` ファイルには以下のコードのセクションが含まれます:
+ `import` ブロック: このブロックを使用して、[AWS SDK クライアント](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/the-request-object.html)などの Lambda 関数に必要なライブラリを含めます。
+ `const s3Client` 宣言: ハンドラー関数の外部で [Amazon S3 クライアント](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)を初期化します。これにより、Lambda は[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)中にこのコードを実行し、クライアントは[複数の呼び出しで再利用](lambda-runtime-environment.md#execution-environment-reuse)できるように保持されます。
+ `type OrderEvent`: 予想される入力イベントの構造を定義します。
+ `export const handler`: Lambda が呼び出すメインハンドラー関数です。関数をデプロイするときは、[ハンドラー](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)プロパティに `index.handler` を指定します。`Handler` プロパティの値は、エクスポートされたハンドラーメソッドのファイル名と名前で、ドットで区切られます。
+ `uploadReceiptToS3` 関数: これは、メインハンドラー関数によって参照されるヘルパー関数です。

この関数が正しく機能するには、[実行ロール](lambda-intro-execution-role.md)で `s3:PutObject` アクションを許可する必要があります。また、必ず `RECEIPT_BUCKET` 環境変数を定義してください。呼び出しに成功したら、Amazon S3 バケットに受信ファイルが含まれているはずです。

## CommonJS および ES モジュール
<a name="typescript-commonjs-es-modules"></a>

Node.js は CommonJS モジュールと ECMAScript モジュール (ES モジュール) の 2 つのモジュールシステムに対応しています。Lambda では、top-level await をサポートしている ES モジュールを使用することをお勧めします。これにより、[実行環境の初期化](#typescript-initialization)中に非同期タスクを完了できます。

Node.js は `.cjs` ファイル名拡張子を持つファイルを CommonJS モジュールとして扱い、`.mjs` 拡張子は ES モジュールを示します。デフォルトでは、Node.js は `.js` ファイル名拡張子を持つファイルを CommonJS モジュールとして扱います。関数の `package.json` ファイルで `type` を `module` として指定することで、`.js` ファイルを ES モジュールとして扱うように Node.js を設定できます。`NODE_OPTIONS` 環境変数に `—experimental-detect-module` フラグを追加することで、`.js` ファイルを CommonJS として扱うか ES モジュールとして扱うかを自動的に検出するように、Lambda で Node.js を設定できます。詳細については、「[Experimental Node.js features](lambda-nodejs.md#nodejs-experimental-features)」を参照してください。

次の例は、ES モジュールと CommonJS モジュールの両方を使用して記述された関数ハンドラーを示しています。このページの残りの例では、すべて ES モジュールを使用しています。

## Node.js の初期化
<a name="typescript-initialization"></a>

Node.js は、イベントループを使用して効率的な非同期操作をサポートするノンブロッキング I/O モデルを使用します。例えば、Node.js がネットワーク呼び出しを行った場合、関数はネットワークレスポンスをブロックすることなく他のオペレーションを処理し続けます。ネットワークレスポンスを受信すると、コールバックキューに配置されます。キューからのタスクは、現在のタスクが完了すると処理されます。

Lambda では、実行環境の初期化中に開始された非同期タスクが初期化中に完了するように、top-level await を使用することをお勧めします。初期化中に完了しない非同期タスクは通常、最初の関数の呼び出し中に実行されます。これにより、予期しない動作またはエラーが引き起こされる可能性があります。例えば、関数の初期化は、AWS Parameter Store からパラメータを取得するためにネットワーク呼び出しを行う場合があります。初期化中にこのタスクが完了しない場合、呼び出し中に値は null になる可能性があります。初期化と呼び出しの間にも遅延が生じる可能性があり、時間的な制約がある操作でエラーが発生する可能性があります。特に、AWS のサービス呼び出しは時間的制約のあるリクエスト署名に依存する可能性があるため、初期化フェーズ中に呼び出しが完了しない場合、サービス呼び出しは失敗します。初期化中にタスクを完了すると、通常、コールドスタートのパフォーマンスが向上し、プロビジョニングされた同時実行の使用時に最初にパフォーマンスが呼び出されます。詳細情報については、ブログ投稿「[Using Node.js ES modules and top-level await in AWS Lambda](https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda)」を参照してください。

## ハンドラーの命名規則
<a name="typescript-handler-naming"></a>

関数を設定すると、[ハンドラー](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)設定の値はファイル名とエクスポートしたハンドラーメソッドの名前をドットで区切ったものになります。コンソールで作成された関数のデフォルトと、このガイドの例では、`index.handler` です。これは、`index.js` または `index.mjs` ファイルからエクスポートされた `handler` メソッドを示します。

異なるファイル名または関数ハンドラー名を使用してコンソールで関数を作成する場合は、デフォルトのハンドラー名を編集する必要があります。

**関数ハンドラー名を変更するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、関数を選択します。

1. **[コード]** タブを選択します。

1. **[ランタイム設定]** ペインまでスクロールして、**[編集]** を選択します。

1. **[ハンドラー]** には、関数ハンドラーの新しい名前を入力します。

1. **[保存]** を選択します。

## 入力イベントオブジェクトの定義とアクセス
<a name="typescript-example-input"></a>

JSON は Lambda 関数の最も一般的な標準入力形式です。この例では、関数は以下のような入力を想定しています:

```
{
    "order_id": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

TypeScript で Lambda 関数を使用する場合、タイプまたはインターフェイスを使用して入力イベントの形状を定義できます。この例では、タイプを使用してイベント構造を定義します。

```
type OrderEvent = {
    order_id: string;
    amount: number;
    item: string;
}
```

タイプまたはインターフェイスを定義した後、ハンドラーの署名で使用して、タイプの安全性を確保します。

```
export const handler = async (event: OrderEvent): Promise<string> => {
```

コンパイル中、TypeScript はイベントオブジェクトに正しいタイプの必須フィールドが含まれていることを検証します。例えば、`event.order_id` を数値または `event.amount` を文字列として使用しようとすると、TypeScript コンパイラはエラーを報告します。

## TypeScript 関数の有効なハンドラーパターン
<a name="typescript-handler-signatures"></a>

[コールバック](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/using-a-callback-function.html)を使用する代わりに、[async/await](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/using-async-await.html) を使用して関数ハンドラーを宣言することをお勧めします。async/await は、非同期コードを記述するための簡潔で読みやすい方法であり、ネストされたコールバックや連鎖する promise を必要としません。async/await を使用すると、非同期かつノンブロッキングでありながら、同期コードのように読み取るコードを記述できます。

このセクションの例では `S3Event` タイプを使用します。ただし、[@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) パッケージで他の AWS イベントタイプを使用することも、独自のイベントタイプを定義することもできます。@types/aws-lambda からタイプを使用するには:

1. @types/aws-lambda パッケージを開発の依存関係として追加します。

   ```
   npm install -D @types/aws-lambda
   ```

1. `Context`、`S3Event`、`Callback` など、必要なタイプをインポートします。

### 非同期関数ハンドラー (推奨)
<a name="typescript-handler-async"></a>

`async` キーワードは関数を非同期としてマークし、`await` キーワードは `Promise` が解決されるまで関数の実行を一時停止します。ハンドラーは次の引数を取ります。
+ `event`: 関数に渡された入力データが含まれます。
+ `context`: 呼び出し、関数、および実行環境に関する情報が含まれます。詳細については、「[Lambda コンテキストオブジェクトを使用して TypeScript 関数の情報を取得する](typescript-context.md)」を参照してください。

async/await パターンの有効な署名は次のとおりです。

```
export const handler = async (event: S3Event): Promise<void> => { };
```

```
export const handler = async (event: S3Event, context: Context): Promise<void> => { };
```

**注記**  
項目の配列を非同期で処理する場合は、必ず `Promise.all` で待機を使用して、すべてのオペレーションが完了していることを確認します。`forEach` などのメソッドは、非同期コールバックが完了するまで待機することはありません。詳細については、Mozilla ドキュメントの「[Array.prototype.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)」を参照してください。

### 同期関数ハンドラー
<a name="typescript-handler-synchronous"></a>

関数が非同期タスクを実行しない場合は、次のいずれかの関数署名を使用して、同期関数ハンドラーを使用できます。

```
export const handler = (event: S3Event): void => { };
```

```
export const handler = (event: S3Event, context: Context): void => { };
```

### レスポンスストリーミング関数ハンドラー
<a name="typescript-handler-response-streaming"></a>

Lambda は Node.js によるレスポンスストリーミングをサポートしています。レスポンスストリーミング関数ハンドラーは、awslambda.streamifyResponse() デコレータを使用し、イベント、responseStream、コンテキストの 3 つのパラメータを使用します。関数の署名は次のとおりです。

```
export const handler = awslambda.streamifyResponse(async (event: APIGatewayProxyEvent, responseStream: NodeJS.WritableStream, context: Context) => { });
```

詳細については、「Lambda 関数のレスポンスストリーミング」を参照してください。

### コールバックベースの関数ハンドラー
<a name="typescript-handler-callback"></a>

**注記**  
コールバックベースの関数ハンドラーは、Node.js 22 までのみサポートされています。Node.js 24 以降では、非同期タスクは非同期関数ハンドラーを使用して実装する必要があります。

コールバックベースの関数ハンドラーは、イベント、コンテキスト、コールバック引数を使用できます。コールバック引数は、`Error` とレスポンスを想定しており、JSON シリアル化可能である必要があります。

コールバックハンドラーパターンの有効な署名は次のとおりです。

```
export const handler = (event: S3Event, context: Context, callback: Callback<void>): void => { };
```

関数は、[イベントループ](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)が空になるか、関数がタイムアウトするまで実行を続けます。レスポンスは、すべてのイベントループタスクが完了するまで、呼び出し元に送信されません。関数がタイムアウトした場合は、エラーが返ります。すぐにレスポンスが返るようにランタイムを設定するには、[context.callbackWaitsForEmptyEventLoop](typescript-context.md) を false に設定します。

**Example コールバックを持つ TypeScript 関数**  
次の例では、API Gateway 統合に固有の特殊なコールバックタイプである `APIGatewayProxyCallback` を使用します。ほとんどの AWS イベントソースは、上記の署名に示されている汎用 `Callback` タイプを使用します。  

```
import { Context, APIGatewayProxyCallback, APIGatewayEvent } from 'aws-lambda';

export const lambdaHandler = (event: APIGatewayEvent, context: Context, callback: APIGatewayProxyCallback): void => {
    console.log(`Event: ${JSON.stringify(event, null, 2)}`);
    console.log(`Context: ${JSON.stringify(context, null, 2)}`);
    callback(null, {
        statusCode: 200,
        body: JSON.stringify({
            message: 'hello world',
        }),
    });
};
```

## ハンドラーでの SDK for JavaScript v3 の使用
<a name="typescript-example-sdk-usage"></a>

多くの場合、Lambda 関数を使用して、他の AWS リソースとやり取りしたり、更新したりします。これらのリソースとインターフェイスする最も簡単な方法は、AWS SDK for JavaScript を使用することです。サポートされているすべての Lambda Node.js ランタイムには、[SDK for JavaScript バージョン 3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/) が含まれています。ただし、デプロイパッケージに必要な AWS SDK クライアントを含めることを強くお勧めします。これにより、将来の Lambda ランタイム更新時の[下位互換性](runtimes-update.md#runtime-update-compatibility)が最大化されます。

SDK 依存関係を関数に追加するには、必要な特定の SDK クライアントに `npm install` コマンドを使用します。サンプルコードでは、[Amazon S3 クライアント](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)を使用しました。この依存関係を追加するには、`package.json` ファイルが格納されているディレクトリで以下のコマンドを実行します。

```
npm install @aws-sdk/client-s3
```

関数コードで、関数の例で示すように、必要なクライアントとコマンドをインポートします。

```
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
```

次に、[Amazon S3 クライアント](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)を初期化します。

```
const s3Client = new S3Client();
```

この例では、関数を呼び出すたびに Amazon S3 クライアントを初期化する必要がないように、メインハンドラー関数の外で Amazon S3 クライアントを初期化しました。SDK クライアントを初期化したら、それを使用してその AWS サービスの API コールを行うことができます。サンプルコードは、以下のように Amazon S3 [PutObject](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/PutObjectCommand/) API アクションを呼び出します。

```
const command = new PutObjectCommand({
    Bucket: bucketName,
    Key: key,
    Body: receiptContent
});
```

## 環境変数にアクセスする
<a name="typescript-example-envvars"></a>

ハンドラーコードでは、`process.env` を使用して任意の[環境変数](configuration-envvars.md)を参照できます。この例では、以下のコード行を使用して、定義された `RECEIPT_BUCKET` 環境変数を参照します:

```
// Access environment variables
const bucketName = process.env.RECEIPT_BUCKET;
if (!bucketName) {
    throw new Error('RECEIPT_BUCKET environment variable is not set');
}
```

## グローバルな状態を使用する
<a name="typescript-handler-state"></a>

Lambda は、関数を初めて呼び出す前の[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)で静的コードを実行します。初期化中に作成されたリソースは呼び出し間でメモリに保持されるため、関数を呼び出すたびにリソースを作成する必要がなくなります。

コード例では、S3 クライアント初期化コードはハンドラーの外にあります。ランタイムは、関数が最初のイベントを処理する前にクライアントを初期化し、クライアントはすべての呼び出しで再利用できます。

## TypeScript Lambda 関数のコードのベストプラクティス
<a name="typescript-best-practices"></a>

Lambda 関数を構築するときは、次のガイドラインに従ってください。
+ **Lambda ハンドラーをコアロジックから分離します。**これにより、関数の単体テストが実行しやすくなります。
+ **関数のデプロイパッケージ内で依存関係を制御します。**AWS Lambda 実行環境には多数のライブラリが含まれています。Node.js および Python ランタイムの場合、ライブラリには AWS SDK が含まれます。最新の機能やセキュリティ更新プログラムを有効にするために、Lambda はこれらのライブラリを定期的に更新します。この更新により、Lambda 関数の動作が微妙に変化する場合があります。関数で使用する依存関係を完全に制御するには、すべての依存関係をデプロイパッケージでパッケージングします。
+ **依存関係の複雑さを最小限に抑えます。**フレームワークを単純化して、[実行環境](lambda-runtime-environment.md)起動時のロードを高速化します。
+ **デプロイパッケージをランタイムに必要な最小限のサイズにします。**これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。

**実行環境の再利用を活用して関数のパフォーマンスを向上させます。**関数ハンドラー外で SDK クライアントとデータベース接続を初期化し、静的なアセットを `/tmp` ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、関数の実行時間が短縮され、コストが節約されます。

呼び出し間でデータが漏れるのを防ぐため、実行環境を使用してセキュリティ上の懸念があるユーザーデータ、イベント、またはその他の情報を保存しないでください。関数がハンドラー内のメモリに保存できない変更可能な状態に依存している場合は、ユーザーごとに個別の関数または個別のバージョンの関数を作成することを検討してください。

**keep-alive ディレクティブを使用して永続的な接続を維持します。**Lambda は、時間の経過とともにアイドル状態の接続を消去します。関数を呼び出すときにアイドル状態の接続を再利用しようとすると、接続エラーが発生します。永続的な接続を維持するには、ランタイムに関連付けられている keep-alive ディレクティブを使用します。例については、「[Node.js で Keep-alive を使用して接続を再利用する](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)」を参照してください。

**[環境変数](configuration-envvars.md)を使用して、オペレーショナルパラメータを関数に渡します。**たとえば、Amazon S3 バケットに書き込む場合、書き込み先のバケット名はハードコーディングせずに、環境変数として設定します。

Lambda 関数では、**再帰呼び出しを使用しないでください**。関数が自身を呼び出すこともあれば、新たに開始されたプロセスで関数が再度呼び出される可能性もあります。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。意図しない呼び出しがいくつも見つかった場合は、すぐに関数の予約済同時実行数を `0` に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。

Lambda 関数コードで**文書化されていない非公開の API を使用しないでください**。AWS Lambda マネージドランタイムでは、Lambda が Lambda の内部 API にセキュリティと機能面の更新を定期的に適用します。これらの内部 API 更新には後方互換性がないことがあり、関数にこれらの非公開 API に対する依存関係がある場合、呼び出しの失敗などの意図しない結果につながります。公開されている API のリストについては、「[API リファレンス](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)」を参照してください。

**冪等性コードを記述します。**関数の記述に冪等性コードを使用すると、重複するイベントが同じ方法で処理されるようになります。コードでは、イベントを適切に検証し、重複するイベントを適切に処理する必要があります。詳細については、「[Lambda 関数を冪等にするにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)」を参照してください。