ข้ามไปยังเนื้อหา

AssemblyScript

AssemblyScript คือคอมไพเลอร์ที่แปลง TypeScript Subset ที่เข้มงวด ให้เป็น WebAssembly ถ้าคุณรู้จัก TypeScript อยู่แล้ว คุณสามารถเริ่มใช้ AssemblyScript ได้ในไม่กี่นาที ไม่มี Borrow Checker ของ Rust ไม่มีการจัดการ Memory แบบ C — เพียงแค่ TypeScript ที่มี Type และ Annotation เฉพาะของ Wasm

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 .

ไดเรกทอรี assembly/ เก็บไฟล์ Source .ts ของคุณ และ asconfig.json กำหนดค่าคอมไพเลอร์

เปิด 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;
}

ความแตกต่างหลักจาก TypeScript ทั่วไป:

  • Type อย่าง i32, i64, f32, f64 คือ Numeric Type ของ Wasm ไม่ใช่ number ของ TypeScript
  • ไม่มี any, ไม่มี unknown และไม่มีการแปลง Type โดยอัตโนมัติ
  • export ทำให้ฟังก์ชันเข้าถึงได้จาก JavaScript (เหมือน (export ...) ใน WAT)
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

หรือใช้ WebAssembly API โดยตรงโดยไม่ต้องใช้ 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

Editor ด้านล่างเปิดโปรเจกต์ AssemblyScript ใน StackBlitz ที่คุณสามารถแก้ไข คอมไพล์ และรันโค้ดใน browser ได้โดยตรง

AssemblyScript

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

ตัวเลือกBenefitCost
AssemblyScriptSyntax คุ้นเคยสำหรับคนที่เขียน TypeScript อยู่แล้ว เริ่มต้นได้เร็ว ไม่มี GC หรือ Runtime OverheadEcosystem จำกัดมากเมื่อเทียบกับ Rust หรือ C และ ไม่ semantically เหมือน TypeScript ทุกจุด — Type System และ Feature Set ต่างกัน
Rust + wasm-bindgenMemory Safety จาก Ownership Model, Binary Size เล็ก, Ecosystem ใหญ่กว่าLearning Curve สูงกว่ามากสำหรับทีมที่ไม่เคยเขียน Rust (Ownership/Borrowing)
  • คิดว่า AssemblyScript คือ TypeScript เต็มรูปแบบ แล้วใช้ Feature ที่ TS รองรับแต่ asc ไม่รองรับ (เช่น Union Type ซับซ้อน หรือ any) จนเจอ Compile Error ที่ไม่คาดคิด
  • ลืมว่า number ของ TypeScript ไม่มีอยู่จริงใน AssemblyScript ต้องระบุ i32/i64/f32/f64 ให้ชัดเจนเสมอ
  • เลือก AssemblyScript สำหรับงานที่ต้องพึ่ง Library จำนวนมาก (เช่น Image Processing ที่ซับซ้อน) โดยไม่เช็ค Ecosystem ก่อน จนต้องเขียน Logic เองใหม่ทั้งหมด

💡 ตัวอย่างจากของจริง

AssemblyScript เคยถูกใช้คอมไพล์ Smart Contract เป็น Wasm มาก่อน — NEAR Protocol เคยมี SDK ทางการชื่อ near-sdk-as สำหรับสิ่งนี้โดยเฉพาะ — แต่ ณ ปลายปี 2026 SDK ตัวนี้ถูก archive ไปแล้ว และเอกสารของ NEAR เองก็แนะนำ Rust เป็นภาษาหลักสำหรับเขียน Contract แทน ซึ่งเป็นตัวอย่างเตือนใจที่ดีว่าควรเช็คสถานะปัจจุบันของ toolchain มากกว่าเชื่อ claim เก่า (near-sdk-as บน GitHub)

AssemblyScript ใช้ Numeric Type ใดสำหรับเลขจำนวนเต็ม 32 บิต?
จะทำให้ฟังก์ชัน AssemblyScript เรียกได้จาก JavaScript ได้อย่างไร?
'npx asinit .' ทำอะไรเมื่อสร้าง Scaffolding โปรเจกต์ AssemblyScript?
ทำไม AssemblyScript จึงผลิต Wasm Binary ขนาดเล็ก?