TypeScript Config Example

The same basic service as the YAML example, rewritten as a typed serverless.ts

When to use TypeScript config

TypeScript configuration is useful when you want type-checked serverless definitions, need to compute values at parse time (e.g. from environment variables), or want to share types between your application code and infrastructure config.

Install dependencies

npm install --save-dev typescript ts-node @types/node @serverless/typescript

serverless.ts

import type { AWS } from '@serverless/typescript';

const stage = process.env.STAGE ?? 'dev';
const region = 'us-east-1';

const serverlessConfig: AWS = {
  service: 'items-api',
  frameworkVersion: '3',
  provider: {
    name: 'aws',
    runtime: 'nodejs20.x',
    region,
    stage,
    environment: {
      TABLE_NAME: `items-${stage}`,
      STAGE: stage,
    },
  },
  functions: {
    listItems: {
      handler: 'src/list.handler',
      description: 'List all items',
      memorySize: 256,
      timeout: 10,
      events: [
        {
          http: {
            path: '/items',
            method: 'get',
            cors: true,
          },
        },
      ],
    },
    createItem: {
      handler: 'src/create.handler',
      description: 'Create a new item',
      memorySize: 256,
      timeout: 10,
      events: [
        {
          http: {
            path: '/items',
            method: 'post',
            cors: true,
          },
        },
      ],
    },
  },
  resources: {
    Resources: {
      ItemsTable: {
        Type: 'AWS::DynamoDB::Table',
        Properties: {
          TableName: `items-${stage}`,
          BillingMode: 'PAY_PER_REQUEST',
          AttributeDefinitions: [{ AttributeName: 'id', AttributeType: 'S' }],
          KeySchema: [{ AttributeName: 'id', KeyType: 'HASH' }],
        },
      },
    },
  },
};

export default serverlessConfig;

main.tf

terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

module "serverless" {
  source        = "./modules/sls.tf"
  config_path   = "${path.root}/serverless.ts"
  config_format = "typescript"

  # STAGE is read by serverless.ts at parse time
  environment_vars = {
    STAGE = "production"
  }
}

outputs.tf

output "api_url" {
  value = module.serverless.api_gateway_invoke_url
}

output "function_arns" {
  value = module.serverless.function_arns
}

output "table_name" {
  value = module.serverless.custom_dynamodb_table_names["ItemsTable"]
}

Deploy

terraform init
terraform plan
terraform apply

Async configuration

For more advanced use cases you can export an async function. sls.tf's TypeScript parser will await it before continuing:

import type { AWS } from '@serverless/typescript';
import { readFileSync } from 'fs';

// Load a shared config file at parse time
const sharedConfig = JSON.parse(readFileSync('./config.json', 'utf8'));

const getConfig = async (): Promise<AWS> => {
  const stage = process.env.STAGE ?? 'dev';
  return {
    service: sharedConfig.serviceName,
    provider: {
      name: 'aws',
      runtime: 'nodejs20.x',
      region: sharedConfig.region,
      stage,
    },
    functions: {
      handler: {
        handler: 'dist/index.handler',
        events: [{ http: { path: '/{proxy+}', method: 'any' } }],
      },
    },
  };
};

export default getConfig;

Next steps