Recently, I have been gotten into Alexa skill development. In a nutshell, an Alexa skill is just a Lambda function that is triggered by an Alexa request referred to as an "intent" which you define in your intent model. Different "handlers" are then setup to perform the intended actions and respond appropriately. You can write your handlers in JavaScript, Python, or Java. I am not the most familiar with Python or Java, so I decided to write my skill in JavaScript.
However, I missed the type safety, developer experience, and built in documentation that TypeScript provides. So, I decided to rewrite my skill in TypeScript. Unfortunately, I found that there was not a lot of documentation on how to do this. (If you know of any, please let me know!) But, I know that TypeScript is JavaScript at the end of the day therefor it should be possible in theory. I just had to figure out how to do it. After a lot of trial and error, I finally got it working. Here is how I did it.
Before we get started, big shout out to this forum post where the last responded provided the key piece of information I needed to get this working.
Prerequisites
- An Alexa Developer account
- An Alexa Skill that you have already created for the Node environment I will not be covering how to create an Alexa Skill in this post. If you need help with that, check out this tutorial.
Step 1: Install TypeScript to your project
Navigate to the lambda
directory of your project and run the following command:
npm install typescript
Note: I am adding TypeScript as a standard dependency because the Ask pipeline always runs
npm install --production
before deploying your code. If you add TypeScript as a dev dependency, it will not be installed when your code is compiled which will make your deploy fail.
Step 2: Create a tsconfig.json file
Run tsc --init
to create a tsconfig.json
file. This file will tell the TypeScript compiler how to compile your code. I recommend using the following settings:
{
"compilerOptions": {
"alwaysStrict" : true,
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "es2017",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"composite": true,
"noUnusedLocals": false,
"skipLibCheck": true,
"noUnusedParameters": false,
"allowSyntheticDefaultImports": true
},
"include": [
"src/**/*"
],
"exclude": ["node_modules"]
}
Step 3: Create a [object Object] directory
From what I can tell, the Alexa deploy job will only look for an index.js
file in the lambda
directory as the entry point for your Lambda function. However, we want our source code to all be in TypeScript, including our TS compiler entry point index.ts
file. So, we need to create a src
directory to hold all of our TypeScript files. My file structure looks like this:
// Within the lambda directory
└───src
├───handlers
│ ├───customHandlers
│ ├───defaultHandlers
│ └───index.ts
│───utils
│───index.js
│───package.json
└───tsconfig.json
Note: There will be a
dist
directory next tosrc
in thelambda
directory as well, but that will be created when we compile our TypeScript code.
Step 4: Tell index.js to look for the compiled index.js file
As I said before, the Alexa deploy job will only look for an index.js
file in the lambda
directory as the entry point for your Lambda function. So, we need to essentially use that file as a proxy to our compiled index.js
file in the dist
directory. To do this, we need to add the following code to the index.js
file in the lambda
directory:
const skill = require('./dist/index');
exports.handler = skill.handler;
Step 5: Compile your TypeScript code and cleanup on deploy
Now that we have everything setup, we need to setup our deploy job to compile our TypeScript code and cleanup after itself. To do this, we need to add the following to the package.json
file.
"scripts": {
"clean": "npx rimraf ./dist ./tsconfig.tsbuildinfo",
"postinstall": "npm run clean && npm run build",
"compile": "tsc --build tsconfig.json --pretty",
"test": "jest --coverage",
"build": "npm run compile"
}
I am not 100% sure if the clean
or postinstall
scripts are necessary, but I added them just in case at the recommendation of the last answer in the forum post I mentioned earlier. I also added a test
script because I am using Jest for unit testing. You can add whatever scripts you need to this file.
And I believe that is it! You should now be able to write your Alexa Skill in TypeScript.
Other helpful tips
- Sometimes your changes do not always get fully uploaded and deployed when you push to master. If you are having trouble getting your changes to show up, try updating the package version in the
package.json
file. This seems to guarantee that your changes will be deployed. - Install the
@types/aws-sdk
and@types/node
packages to get type definitions for the AWS SDK and Node.js. - Eat red meat and work out. It's good for you. 🐄