Define Lambda function handler in TypeScript - Amazon Lambda
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Define Lambda function handler in TypeScript

The Lambda function handler is the method in your function code that processes events. When your function is invoked, Lambda runs the handler method. Your function runs until the handler returns a response, exits, or times out.

Example TypeScript handler

This example function logs the contents of the event object and returns the location of the logs. Note the following:

  • Before using this code in a Lambda function, you must add the @types/aws-lambda package as a development dependency. This package contains the type definitions for Lambda. When @types/aws-lambda is installed, the import statement (import ... from 'aws-lambda') imports the type definitions. It does not import the aws-lambda NPM package, which is an unrelated third-party tool. For more information, see aws-lambda in the DefinitelyTyped GitHub repository.

  • The handler in this example is an ES module and must be designated as such in your package.json file or by using the .mjs file extension. For more information, see see Designating a function handler as an ES module.

import { Handler } from 'aws-lambda'; export const handler: Handler = async (event, context) => { console.log('EVENT: \n' + JSON.stringify(event, null, 2)); return context.logStreamName; };

The runtime passes arguments to the handler method. The first argument is the event object, which contains information from the invoker. The invoker passes this information as a JSON-formatted string when it calls Invoke, and the runtime converts it to an object. When an Amazon service invokes your function, the event structure varies by service. With TypeScript, we recommend using type annotations for the event object. For more information, see Using types for the event object.

The second argument is the context object, which contains information about the invocation, function, and execution environment. In the preceding example, the function gets the name of the log stream from the context object and returns it to the invoker.

You can also use a callback argument, which is a function that you can call in non-async handlers to send a response. We recommend that you use async/await instead of callbacks. Async/await provides improved readability, error handling, and efficiency. For more information about the differences between async/await and callbacks, see Using callbacks.

Using async/await

If your code performs an asynchronous task, use the async/await pattern to make sure that the handler finishes running. Async/await is a concise and readable way to write asynchronous code in Node.js, without the need for nested callbacks or chaining promises. With async/await, you can write code that reads like synchronous code, while still being asynchronous and non-blocking.

The async keyword marks a function as asynchronous, and the await keyword pauses the execution of the function until a Promise is resolved.

Example TypeScript function – asynchronous

This example uses fetch, which is available in the nodejs18.x runtime. Note the following:

  • Before using this code in a Lambda function, you must add the @types/aws-lambda package as a development dependency. This package contains the type definitions for Lambda. When @types/aws-lambda is installed, the import statement (import ... from 'aws-lambda') imports the type definitions. It does not import the aws-lambda NPM package, which is an unrelated third-party tool. For more information, see aws-lambda in the DefinitelyTyped GitHub repository.

  • The handler in this example is an ES module and must be designated as such in your package.json file or by using the .mjs file extension. For more information, see see Designating a function handler as an ES module.

import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; const url = 'https://aws.amazon.com/'; export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => { try { // fetch is available with Node.js 18 const res = await fetch(url); return { statusCode: res.status, body: JSON.stringify({ message: await res.text(), }), }; } catch (err) { console.log(err); return { statusCode: 500, body: JSON.stringify({ message: 'some error happened', }), }; } };

Using callbacks

We recommend that you use async/await to declare the function handler instead of using callbacks. Async/await is a better choice for several reasons:

  • Readability: Async/await code is easier to read and understand than callback code, which can quickly become difficult to follow and result in callback hell.

  • Debugging and error handling: Debugging callback-based code can be difficult. The call stack can become hard to follow and errors can easily be swallowed. With async/await, you can use try/catch blocks to handle errors.

  • Efficiency: Callbacks often require switching between different parts of the code. Async/await can reduce the number of context switches, resulting in more efficient code.

When you use callbacks in your handler, the function continues to execute until the event loop is empty or the function times out. The response isn't sent to the invoker until all event loop tasks are finished. If the function times out, an error is returned instead. You can configure the runtime to send the response immediately by setting context.callbackWaitsForEmptyEventLoop to false.

The callback function takes two arguments: an Error and a response. The response object must be compatible with JSON.stringify.

Example TypeScript function with callback

This sample function receives an event from Amazon API Gateway, logs the event and context objects, and then returns a response to API Gateway. Note the following:

  • Before using this code in a Lambda function, you must add the @types/aws-lambda package as a development dependency. This package contains the type definitions for Lambda. When @types/aws-lambda is installed, the import statement (import ... from 'aws-lambda') imports the type definitions. It does not import the aws-lambda NPM package, which is an unrelated third-party tool. For more information, see aws-lambda in the DefinitelyTyped GitHub repository.

  • The handler in this example is an ES module and must be designated as such in your package.json file or by using the .mjs file extension. For more information, see see Designating a function handler as an ES module.

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', }), }); };

Using types for the event object

We recommend that you don’t use the any type for the handler arguments and return type because you lose the ability to check types. Instead, generate an event using the sam local generate-event Amazon Serverless Application Model CLI command, or use an open-source definition from the @types/aws-lambda package.

Generating an event using the sam local generate-event command
  1. Generate an Amazon Simple Storage Service (Amazon S3) proxy event.

    sam local generate-event s3 put >> S3PutEvent.json
  2. Use the quicktype utility to generate type definitions from the S3PutEvent.json file.

    npm install -g quicktype quicktype S3PutEvent.json -o S3PutEvent.ts
  3. Use the generated types in your code.

    import { S3PutEvent } from './S3PutEvent'; export const lambdaHandler = async (event: S3PutEvent): Promise<void> => { event.Records.map((record) => console.log(record.s3.object.key)); };
Generating an event using an open-source definition from the @types/aws-lambda package
  1. Add the @types/aws-lambda package as a development dependency.

    npm install -D @types/aws-lambda
  2. Use the types in your code.

    import { S3Event } from "aws-lambda"; export const lambdaHandler = async (event: S3Event): Promise<void> => { event.Records.map((record) => console.log(record.s3.object.key)); };