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.
Install AssemblyScript
Section titled “Install AssemblyScript”# Create a new Node.js projectmkdir as-demo && cd as-demonpm init -y
# Install the AssemblyScript compilernpm 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.
Write AssemblyScript functions
Section titled “Write AssemblyScript functions”Open assembly/index.ts:
// Integer addition — notice the explicit i32 typesexport function add(a: i32, b: i32): i32 { return a + b;}
// Factorial — recursive, i64 to avoid overflow for larger inputsexport function factorial(n: i64): i64 { if (n <= 1) return 1; return n * factorial(n - 1);}
// Clamp a float value between lo and hiexport 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,f64are Wasm-native numeric types, not TypeScript’snumber. - There is no
any, nounknown, and no implicit type coercion. exportmakes functions accessible from JavaScript (same as WAT’s(export ...)).
Compile with asc
Section titled “Compile with asc”# 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 modulenpx asc assembly/index.ts --outFile build/release.wasm --bindings esmCall from JavaScript
Section titled “Call from JavaScript”// Using the @assemblyscript/loader helperimport { instantiateStreaming } from '@assemblyscript/loader';
const { exports } = await instantiateStreaming(fetch('./build/release.wasm'));
console.log(exports.add(10, 32)); // 42console.log(exports.factorial(BigInt(10))); // 3628800n (i64 → BigInt)console.log(exports.clamp(1.5, 0.0, 1.0)); // 1Or 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)); // 7Try it in the browser
Section titled “Try it in the browser”The editor below opens a live AssemblyScript project in StackBlitz where you can edit, compile, and run the code directly in your browser.
Needs the AssemblyScript toolchain — open in StackBlitz to build & run.
Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
| AssemblyScript | Familiar syntax for anyone already writing TypeScript, fast to get started, no GC or runtime overhead | Much smaller ecosystem than Rust or C, and it is not semantically identical to TypeScript — the type system and feature set differ |
| Rust + wasm-bindgen | Memory safety from the ownership model, small binaries, a much larger ecosystem | A much steeper learning curve for teams new to Rust (ownership/borrowing) |
Common mistakes
Section titled “Common mistakes”- Treating AssemblyScript as full TypeScript and reaching for a feature
ascdoesn’t support (complex union types,any), then hitting an unexpected compile error - Forgetting that TypeScript’s
numberdoesn’t exist in AssemblyScript — you must always specifyi32/i64/f32/f64explicitly - 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-asSDK 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).