Serverless Functions in TypeScript: AWS Lambda from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Serverless Functions in TypeScript: A Complete Guide to AWS Lambda



The serverless architecture has revolutionized the approach to backend development. Instead of managing servers, developers can focus solely on business logic. AWS Lambda is one of the most popular services for running serverless functions. In this guide, we will cover creating, configuring, and deploying Lambda functions in TypeScript — from basic concepts to production-ready solutions.



Why TypeScript for AWS Lambda?



TypeScript adds static typing to JavaScript, which is critically important for serverless functions:



  • Type Safety — prevents errors at compile time
  • Autocompletion — IDE suggests AWS SDK methods
  • Readability — interfaces and types document data structures
  • Scalability — easier to maintain code as the project grows


Project Setup



1. Initialization and Dependency Installation



Create a new project and install the necessary packages:



mkdir my-lambda-projectcd my-lambda-projectnpm init -y

npm install @types/aws-lambda aws-sdknpm install -D typescript ts-node @types/node


2. TypeScript Configuration



Create a tsconfig.json file:



{  "compilerOptions": {    "target": "ES2020",    "module": "commonjs",    "lib": ["ES2020"],    "outDir": "./dist",    "rootDir": "./src",    "strict": true,    "esModuleInterop": true,    "skipLibCheck": true,    "forceConsistentCasingInFileNames": true,    "resolveJsonModule": true,    "declaration": true,    "declarationMap": true,    "sourceMap": true  },  "include": ["src/**/*"],  "exclude": ["node_modules", "dist"]}


Creating Your First Lambda Function



Basic Handler Structure



Create a file src/handler.ts:



import { Handler, APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';

interface UserData { userId: string; name: string; email: string;}

export const handler: Handler<APIGatewayProxyEvent, APIGatewayProxyResult> = async (event) => { try { // Parsing the request body const body: UserData = JSON.parse(event.body || '{}'); // Validation if (!body.userId || !body.name) { return { statusCode: 400, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, body: JSON.stringify({ error: 'Missing required fields' }) }; }

// Business logic const result = { id: body.userId, displayName: body.name.toUpperCase(), createdAt: new Date().toISOString() };

return { statusCode: 200, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, body: JSON.stringify(result) }; } catch (error) { console.error('Error processing request:', error); return { statusCode: 500, body: JSON.stringify({ error: 'Internal server error' }) }; }};


Working with Environment and Secrets



Use environment variables for configuration:



import { Handler } from 'aws-lambda';

interface Config { DB_TABLE: string; MAX_RETRIES: number;}

export const handler: Handler = async (event) => { const config: Config = { DB_TABLE: process.env.DB_TABLE || 'default-table', MAX_RETRIES: parseInt(process.env.MAX_RETRIES || '3', 10) };

// Use AWS Secrets Manager or Parameter Store // for sensitive data return { statusCode: 200, body: JSON.stringify({ table: config.DB_TABLE }) };};


Advanced Techniques



1. Process

Blogs

Book Recommendations