Build
What's new
- no need to define 'main' function
const arr = [1, 2, 3, 4, 5]; for (const b of arr) print(b);
- Accessor for object fields
let obj = { p: 1.0, get value() { return this.p; }, set value(v: number) { this.p = v; }, }
- Class static block
class C { static x: number; static { C.x = 1; } }
-
Migrated to LLVM 19.1.3
-
improved
generating debug informationmore info here: Wiki:How-To
tsc --di --opt_level=0 --emit=exe example.ts- cast from Union Types
let a: string | number = 5; let b: string = a; // b is "5"
- All functions without types are generics
static class Array { public of(...arg) { return arg; } public from(arrayLike) { return [...arrayLike]; } }
- Native types aliases
// byte, short, ushort, int, uint, long, ulong, char, i8, i16, i32, i64, // u8, u16, u32, u64, s8, s16, s32, s64, f16, f32, f64, f128, half, float, double, index const s1: s8 = -1; const s2: u16 = 2; const s3: i32 = 3; const s4: f64 = 1.0;
- Reference types (aka pointers)
let a = [1, 2, 3]; const view: Reference<TypeOf<1>> = ReferenceOf(a[1]); const data = LoadReference(view); const data1 = LoadReference(view[1]);
- Accessor
class Person { static accessor sname: string; accessor name = "no value"; constructor(name: string) { this.name = name; } }
- Explicit Resource Management
function main() { using file = new TempFile(".some_temp_file"); print("done."); } class TempFile { #path: string; #handle: number; constructor(path: string) { this.#path = path; this.#handle = 1; } // other methods [Symbol.dispose]() { // Close the file and delete it. this.#handle = 0; print("dispose"); } }
Planning
- Migrating to LLVM 19.1.3
- Shared libraries
- JavaScript Built-in classes library
Demo
Try it
Chat Room
Want to chat with other members of the TypeScriptCompiler community?
Example
abstract class Department { constructor(public name: string) {} printName(): void { print("Department name: " + this.name); } abstract printMeeting(): void; // must be implemented in derived classes } class AccountingDepartment extends Department { constructor() { super("Accounting and Auditing"); // constructors in derived classes must call super() } printMeeting(): void { print("The Accounting Department meets each Monday at 10am."); } generateReports(): void { print("Generating accounting reports..."); } } function main() { let department: Department; // ok to create a reference to an abstract type department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass department.printName(); department.printMeeting(); //department.generateReports(); // error: department is not of type AccountingDepartment, cannot access generateReports }
Run
tsc --emit=jit --opt --shared-libs=TypeScriptRuntime.dll example.ts
Result
Department name: Accounting and Auditing
The Accounting Department meets each Monday at 10am.
Run as JIT
- with Garbage collection
tsc --emit=jit --opt --shared-libs=TypeScriptRuntime.dll hello.ts
- without Garbage collection
tsc --emit=jit --nogc hello.ts
File hello.ts
function main() { print("Hello World!"); }
Result
Compile as Binary Executable
On Windows
File tsc-compile.bat
set FILENAME=%1 set GC_LIB_PATH=C:\dev\TypeScriptCompiler\__build\gc\msbuild\x64\release\Release set LLVM_LIB_PATH=C:\dev\TypeScriptCompiler\__build\llvm\msbuild\x64\release\Release\lib set TSC_LIB_PATH=C:\dev\TypeScriptCompiler\__build\tsc\windows-msbuild-release\lib set TSCEXEPATH=C:\dev\TypeScriptCompiler\__build\tsc\windows-msbuild-release\bin %TSCEXEPATH%\tsc.exe --opt --emit=exe %FILENAME%.ts
Compile
Run
Result
On Linux (Ubuntu 20.04 and 22.04)
File tsc-compile.sh
FILENAME=$1 export TSC_LIB_PATH=~/dev/TypeScriptCompiler/__build/tsc/linux-ninja-gcc-release/lib export LLVM_LIB_PATH=~/dev/TypeScriptCompiler/3rdParty/llvm/release/lib export GC_LIB_PATH=~/dev/TypeScriptCompiler/3rdParty/gc/release TSCEXEPATH=~/dev/TypeScriptCompiler/__build/tsc/linux-ninja-gcc-release/bin $TSCEXEPATH/tsc --emit=exe $FILENAME.ts --relocation-model=pic
Compile
sh -f tsc-compile.sh hello
Run
Result
Compiling as WASM
On Windows
File tsc-compile-wasm.bat
set FILENAME=%1 set GC_LIB_PATH=C:\dev\TypeScriptCompiler\__build\gc\msbuild\x64\release\Release set LLVM_LIB_PATH=C:\dev\TypeScriptCompiler\__build\llvm\msbuild\x64\release\Release\lib set TSC_LIB_PATH=C:\dev\TypeScriptCompiler\__build\tsc\windows-msbuild-release\lib C:\dev\TypeScriptCompiler\__build\tsc\windows-msbuild-release\bin\tsc.exe --emit=exe --nogc -mtriple=wasm32-unknown-unknown %FILENAME%.ts
Compile
tsc-compile-wasm.bat hello
Run run.html
<!DOCTYPE html> <html> <head></head> <body> <script type="module"> let buffer; let buffer32; let buffer64; let bufferF64; let heap; let heap_base, heap_end, stack_low, stack_high; const allocated = []; const allocatedSize = (addr) => { return allocated["" + addr]; }; const setAllocatedSize = (addr, newSize) => { allocated["" + addr] = newSize; }; const expand = (addr, newSize) => { const aligned_newSize = newSize + (4 - (newSize % 4)) const end = addr + allocatedSize(addr); const newEnd = addr + aligned_newSize; for (const allocatedAddr in allocated) { const beginAllocatedAddr = parseInt(allocatedAddr); const endAllocatedAddr = beginAllocatedAddr + allocated[allocatedAddr]; if (beginAllocatedAddr != addr && addr < endAllocatedAddr && newEnd > beginAllocatedAddr) { return false; } } setAllocatedSize(addr, aligned_newSize); if (addr + aligned_newSize > heap) heap = addr + aligned_newSize; return true; }; const endOf = (addr) => { while (buffer[addr] != 0) { addr++; if (addr > heap_end) throw "out of memory boundary"; }; return addr; }; const strOf = (addr) => String.fromCharCode(...buffer.slice(addr, endOf(addr))); const copyStr = (dst, src) => { while (buffer[src] != 0) buffer[dst++] = buffer[src++]; buffer[dst] = 0; return dst; }; const ncopy = (dst, src, count) => { while (count-- > 0) buffer[dst++] = buffer[src++]; return dst; }; const append = (dst, src) => copyStr(endOf(dst), src); const cmp = (addrL, addrR) => { while (buffer[addrL] != 0) { if (buffer[addrL] != buffer[addrR]) break; addrL++; addrR++; } return buffer[addrL] - buffer[addrR]; }; const prn = (str, addr) => { for (let i = 0; i < str.length; i++) buffer[addr++] = str.charCodeAt(i); buffer[addr] = 0; return addr; }; const clear = (addr, size, val) => { for (let i = 0; i < size; i++) buffer[addr++] = val; }; const aligned_alloc = (size) => { const aligned_size = size + (4 - (size % 4)); if ((heap + aligned_size) > heap_end) throw "out of memory"; setAllocatedSize(heap, aligned_size); const heapCurrent = heap; heap += aligned_size; return heapCurrent; }; const free = (addr) => delete allocated["" + addr]; const realloc = (addr, size) => { if (!expand(addr, size)) { const newAddr = aligned_alloc(size); ncopy(newAddr, addr, allocatedSize(addr)); free(addr); return newAddr; } return addr; } const envObj = { memory: new WebAssembly.Memory({ initial: 256 }), table: new WebAssembly.Table({ initial: 0, element: 'anyfunc', }), fmod: (arg1, arg2) => arg1 % arg2, sqrt: (arg1) => Math.sqrt(arg1), floor: (arg1) => Math.floor(arg1), pow: (arg1, arg2) => Math.pow(arg1, arg2), fabs: (arg1) => Math.abs(arg1), _assert: (msg, file, line) => console.assert(false, strOf(msg), "| file:", strOf(file), "| line:", line, " DBG:", path), puts: (arg) => output += strOf(arg) + '\n', strcpy: copyStr, strcat: append, strcmp: cmp, strlen: (addr) => endOf(addr) - addr, malloc: aligned_alloc, realloc: realloc, free: free, memset: (addr, size, val) => clear(addr, size, val), atoi: (addr, rdx) => parseInt(strOf(addr), rdx), atof: (addr) => parseFloat(strOf(addr)), sprintf_s: (addr, sizeOfBuffer, format, ...args) => { const formatStr = strOf(format); switch (formatStr) { case "%d": prn(buffer32[args[0] >> 2].toString(), addr); break; case "%g": prn(bufferF64[args[0] >> 3].toString(), addr); break; case "%llu": prn(buffer64[args[0] >> 3].toString(), addr); break; default: throw "not implemented"; } return 0; }, } const config = { env: envObj, }; WebAssembly.instantiateStreaming(fetch("./hello.wasm"), config) .then(results => { const { main, __wasm_call_ctors, __heap_base, __heap_end, __stack_low, __stack_high } = results.instance.exports; buffer = new Uint8Array(results.instance.exports.memory.buffer); buffer32 = new Uint32Array(results.instance.exports.memory.buffer); buffer64 = new BigUint64Array(results.instance.exports.memory.buffer); bufferF64 = new Float64Array(results.instance.exports.memory.buffer); heap = heap_base = __heap_base, heap_end = __heap_end, stack_low = __stack_low, stack_high = __stack_high; try { if (__wasm_call_ctors) __wasm_call_ctors(); main(); } catch (e) { console.error(e); } }); </script> </body> </html>
Build
On Windows
Requirements:
Visual Studio 2022- 512GB of free space on disk
First, precompile dependencies
cd TypeScriptCompiler
prepare_3rdParty.bat To build TSC binaries:
cd TypeScriptCompiler\tsc
config_tsc_release.bat
build_tsc_release.batOn Linux (Ubuntu 20.04 and 22.04)
Requirements:
GCCorClang- 512GB of free space on disk
- sudo apt-get install
libtinfo-dev
First, precompile dependencies
chmod +x *.sh cd ~/TypeScriptCompiler ./prepare_3rdParty.sh
To build TSC binaries:
cd ~/TypeScriptCompiler/tsc chmod +x *.sh ./config_tsc_release.sh ./build_tsc_release.sh


