Skip to content

AssemblyScript

AssemblyScript is a compiler that turns a strict subset of TypeScript into WebAssembly. If you already know TypeScript, you can be productive in AssemblyScript in minutes. There is no Rust borrow checker, no C memory management — just typed TypeScript with a few Wasm-specific annotations.

Terminal window
# Create a new Node.js project
mkdir as-demo && cd as-demo
npm init -y
# Install the AssemblyScript compiler
npm install --save-dev assemblyscript
# Scaffold the project (creates assembly/ and tsconfig.json)
npx asinit .

The assembly/ directory holds your .ts source files. asconfig.json configures the compiler.

Open assembly/index.ts:

// Integer addition — notice the explicit i32 types
export function add(a: i32, b: i32): i32 {
return a + b;
}
// Factorial — recursive, i64 to avoid overflow for larger inputs
export function factorial(n: i64): i64 {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// Clamp a float value between lo and hi
export function clamp(value: f64, lo: f64, hi: f64): f64 {
if (value < lo) return lo;
if (value > hi) return hi;
return value;
}

Key differences from regular TypeScript:

  • Types like i32, i64, f32, f64 are Wasm-native numeric types, not TypeScript’s number.
  • There is no any, no unknown, and no implicit type coercion.
  • export makes functions accessible from JavaScript (same as WAT’s (export ...)).
Terminal window
# Development build (readable, not optimised)
npx asc assembly/index.ts --outFile build/release.wasm --textFile build/release.wat
# Release build (optimised, smaller binary)
npx asc assembly/index.ts --outFile build/release.wasm --optimize
# With bindings for use as an ES module
npx asc assembly/index.ts --outFile build/release.wasm --bindings esm
// Using the @assemblyscript/loader helper
import { instantiateStreaming } from '@assemblyscript/loader';
const { exports } = await instantiateStreaming(fetch('./build/release.wasm'));
console.log(exports.add(10, 32)); // 42
console.log(exports.factorial(BigInt(10))); // 3628800n (i64 → BigInt)
console.log(exports.clamp(1.5, 0.0, 1.0)); // 1

Or use the WebAssembly API directly without the loader:

const response = await fetch('./build/release.wasm');
const bytes = await response.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, {});
console.log(instance.exports.add(3, 4)); // 7

The editor below opens a live AssemblyScript project in StackBlitz where you can edit, compile, and run the code directly in your browser.

AssemblyScript

Needs the AssemblyScript toolchain — open in StackBlitz to build & run.

OptionBenefitCost
AssemblyScriptFamiliar syntax for anyone already writing TypeScript, fast to get started, no GC or runtime overheadMuch smaller ecosystem than Rust or C, and it is not semantically identical to TypeScript — the type system and feature set differ
Rust + wasm-bindgenMemory safety from the ownership model, small binaries, a much larger ecosystemA much steeper learning curve for teams new to Rust (ownership/borrowing)
  • Treating AssemblyScript as full TypeScript and reaching for a feature asc doesn’t support (complex union types, any), then hitting an unexpected compile error
  • Forgetting that TypeScript’s number doesn’t exist in AssemblyScript — you must always specify i32/i64/f32/f64 explicitly
  • Choosing AssemblyScript for work that depends on a large library ecosystem (e.g. complex image processing) without checking that ecosystem first, ending up rewriting everything from scratch

💡 Real-world example

AssemblyScript has been used for compiling smart contracts to Wasm — NEAR Protocol shipped an official near-sdk-as SDK for exactly that — though as of late 2026 that SDK is archived and NEAR’s own docs now recommend Rust as the primary contract language, a useful reminder to check a toolchain’s current status rather than an older claim about it (near-sdk-as on GitHub).

Which numeric type does AssemblyScript use for a 32-bit integer?
How do you make an AssemblyScript function callable from JavaScript?
What does 'npx asinit .' do when scaffolding an AssemblyScript project?
Why does AssemblyScript produce small Wasm binaries?