All our expressions are written for the newer JavaScript Expressions Engine

Blog

How to write After Effects expressions in TypeScript

Photo of Tim Haywood
Tim Haywood

|

August 13, 2020

In this article we'll go over how to write expressions libraries, (.jsx) files, in TypeScript, with automatic refresh, using Rollup.js.

typescript to after effects diagram

This means you can write expressions with the full benefits of:

  • Type checking
type checking of after effects functions
  • Auto-completion
auto completion of expressions
  • Testing
js
// src/index.test.ts
import { welcome } from "./index";
test("returns correct welcome string", () => {
expect(welcome("test")).toEqual("Welcome test!");
});

All while working in working in VS Code, that will re-compile and update in After Effects on save.

This article assumes you're familiar with tools such as Git, GitHub, NPM.

If you're not sure what these are, feel free to read on but you may encounter issues.

You can also watch our tutorial on the topic below:

Play Youtube video

Quick setup

  • Create a new project using create-expression-lib
bash
npx create-expression-lib project-name --install

And then navigate into the project folder via:

bash
cd project-name
  • Edit the /src files

Any code exported from src/index.ts file will be output to dist/index.jsx as a After Effects compatible .jsx file.

  • Run rollup in watch mode
bash
npm run watch

This will re-compile your files into After Effects compatible .jsx files every time you save.

  • Import the file into After Effects

You can then import the output .jsx file into After Effects, and use it in your expressions, for example.

js
const libraryCode = footage("index.jsx").sourceData;
libraryCode.someFunction();

After Effects will reload the .jsx file when it's recompiled, so you'll see the result of your code every time you save your source file.

Using the After Effects API

Since you're writing expressions outside of After Effects, native attributes and native methods such as thisComp, linear() and wiggle() aren't defined when you're writing the code.

To add type safety and auto completion for After Effects variables and functions, this setup uses the package expression-globals-typescript.

This package mocks the After Effects API in TypeScript, so you can write expressions outside of an After Effects environment.

Classes

To create layers, compositions and properties, you can use the classes exported from the library. For example:

ts
import { Comp, Layer } from "expression-globals-typescript";
const thisComp = new Comp();
const thisLayer = new Layer();

To create properties (such as position or scale), you can use the Property class.

ts
import { Property, Vector } from "expression-globals-typescript";
const thisProperty = new Property<Vector>([0, 100]);

The Property constructor takes a value to set as the property value, and a type (<>) to set as the type for the property.

After Effects Types

You can import After Effect's specific types such as Color and Vector from the package to properly type your expressions.

typescript
import { Color, Vector } from "expression-globals-typescript";
const textColor: Color = [1, 1, 1, 1];
const textPosition: Vector = [950, 540];

To see all the Types and Base Objects available, see the expression-globals-typescript source code.

How it works

Creating releases

To distribute the output (.jsx) file via GitHub releases, you can run the release command:

bash
npm run release

This will create a new release on GitHub using the GitHub CLI, attaching the output dist file to the release.

You will need to have the GitHub CLI installed on your machine for this to work.

There's two settings in your package.json that affect the release:

  • The release version comes from the "version"
  • You can set which file to attach to the release in the release script, which is dist/index.jsx by default

The "version" is also added to the output .jsx file at build time.

Testing

Expressions Library Template comes configured with Jest and ts-jest. This enables you to write tests for your expressions that will run on each save, giving you confidence that any code changes haven't broken your expression library.

For more details on writing tests with Jest, see the Jest docs.

You can write tests in the src/index.test.ts file, importing the code you want to test from index.ts. For example:

js
// src/index.test.ts
import { welcome } from "./index";
test("returns correct welcome string", () => {
expect(welcome("test")).toEqual("Welcome test!");
});

And then run the test suite in watch mode via the command:

bash
npm run test

For a more detailed example of writing tests for expressions, you can view the tests for our eKeys library.

Splitting expressions across files

To split your expression into multiple files, all you need to do is:

  • Export from one file
typescript
// anotherFile.ts
const someVariable: string = "this is in another file";
export { someVariable };
  • Import and export from the index file
typescript
// index.ts
import { someVariable } from "./anotherFile";
const localVariable: number = 2;
export { someVariable, localVariable };

They will then be bundled into the output file at build time.

Blog

For enquiries contact us at hey@motiondeveloper.com