AssemblyScript
AssemblyScript คือคอมไพเลอร์ที่แปลง TypeScript Subset ที่เข้มงวด ให้เป็น WebAssembly ถ้าคุณรู้จัก TypeScript อยู่แล้ว คุณสามารถเริ่มใช้ AssemblyScript ได้ในไม่กี่นาที ไม่มี Borrow Checker ของ Rust ไม่มีการจัดการ Memory แบบ C — เพียงแค่ TypeScript ที่มี Type และ Annotation เฉพาะของ Wasm
ติดตั้ง AssemblyScript
หัวข้อที่มีชื่อว่า “ติดตั้ง AssemblyScript”# สร้างโปรเจกต์ Node.js ใหม่mkdir as-demo && cd as-demonpm init -y
# ติดตั้งคอมไพเลอร์ AssemblyScriptnpm install --save-dev assemblyscript
# สร้างโครงสร้างโปรเจกต์ (สร้าง assembly/ และ tsconfig.json)npx asinit .ไดเรกทอรี assembly/ เก็บไฟล์ Source .ts ของคุณ และ asconfig.json กำหนดค่าคอมไพเลอร์
เขียนฟังก์ชัน AssemblyScript
หัวข้อที่มีชื่อว่า “เขียนฟังก์ชัน AssemblyScript”เปิด assembly/index.ts:
// การบวกเลขจำนวนเต็ม — สังเกตประเภท i32 ที่ระบุชัดเจนexport function add(a: i32, b: i32): i32 { return a + b;}
// Factorial — แบบ Recursive, ใช้ i64 เพื่อป้องกัน Overflow สำหรับ Input ขนาดใหญ่export function factorial(n: i64): i64 { if (n <= 1) return 1; return n * factorial(n - 1);}
// Clamp ค่า Float ระหว่าง lo และ hiexport 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)
คอมไพล์ด้วย asc
หัวข้อที่มีชื่อว่า “คอมไพล์ด้วย asc”# Development Build (อ่านได้ง่าย, ไม่ Optimise)npx asc assembly/index.ts --outFile build/release.wasm --textFile build/release.wat
# Release Build (Optimise แล้ว, Binary เล็กกว่า)npx asc assembly/index.ts --outFile build/release.wasm --optimize
# พร้อม Binding สำหรับใช้เป็น ES Modulenpx asc assembly/index.ts --outFile build/release.wasm --bindings esmเรียกใช้จาก JavaScript
หัวข้อที่มีชื่อว่า “เรียกใช้จาก JavaScript”// ใช้ @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)); // 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ลองใช้งานใน browser
หัวข้อที่มีชื่อว่า “ลองใช้งานใน browser”Editor ด้านล่างเปิดโปรเจกต์ AssemblyScript ใน StackBlitz ที่คุณสามารถแก้ไข คอมไพล์ และรันโค้ดใน browser ได้โดยตรง
Needs the AssemblyScript toolchain — open in StackBlitz to build & run.
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| AssemblyScript | Syntax คุ้นเคยสำหรับคนที่เขียน TypeScript อยู่แล้ว เริ่มต้นได้เร็ว ไม่มี GC หรือ Runtime Overhead | Ecosystem จำกัดมากเมื่อเทียบกับ Rust หรือ C และ ไม่ semantically เหมือน TypeScript ทุกจุด — Type System และ Feature Set ต่างกัน |
| Rust + wasm-bindgen | Memory 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 เองใหม่ทั้งหมด
💡 ตัวอย่างจากของจริง
NEAR Protocol ใช้ AssemblyScript เป็นหนึ่งในภาษาหลักสำหรับเขียน Smart Contract ที่คอมไพล์เป็น Wasm และ Shopify Functions ก็รองรับ AssemblyScript เป็นตัวเลือกให้ Merchant เขียน Custom Checkout Logic ควบคู่กับ Rust