Skip to content

What's new

ASDAlexander77 edited this page Jun 27, 2026 · 9 revisions

What's New

A tour of the TypeScript language features and compiler options supported by TypeScriptCompiler (tsc). Each section below shows a short, runnable snippet.

Most examples can be compiled and run directly, e.g. tsc --emit=exe example.ts.

Contents


Object-Oriented Programming

Index signatures for classes and interfaces

Declare an index signature and back it with get/set methods. Interfaces may also declare property getters.

class Test {
    // declare the index (get/set methods are bound to it)
    [index1: number]: string;

    get(index: number): string {
        return "index";
    }

    set(index: number, value: string) {
    }

    get val(): string {
        return "prop";
    }
}

interface ITest {
    [index1: number]: string;

    get val(): string;
}

const t = new Test();
print(t[10]);

const ti: ITest = t;
print(ti[10]);
print(ti.val);

Accessors 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;
    }
}

Accessor keyword (static and instance)

class Person {
    static accessor sname: string;
    accessor name = "no value";
    constructor(name: string) {
        this.name = name;
    }
}

Generic methods

class Lib {
    static max<T>(a: T, b: T): T {
        return a > b ? a : b;
    }
}

function main() {
    assert(Lib.max(10, 20) == 20);
    assert(Lib.max("a", "b") == "b");
    assert(Lib.max<number>(20, 30) == 30);
    print("done.");
}

Type System

Cast from union types

let a: string | number = 5;
let b: string = a; // b is "5"

Untyped functions are generic

Functions and methods declared without explicit parameter types are treated as generics.

static class Array {
    public of(...arg) {
        return arg;
    }

    public from(arrayLike) {
        return [...arrayLike];
    }
}

Native type aliases

// Available 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 (pointers)

Ref(x) takes a reference (address) of an lvalue, and Deref(ref) reads the value back through it.

let a = [1, 2, 3];
const view: Ref<TypeOf<1>> = Ref(a[1]);
const data = Deref(view);
const data1 = Deref(view[1]);

ReferenceOf / LoadReference (and the Reference<T> type) remain available as deprecated aliases of Ref / Deref / Ref<T>.

Literal type widening

function main()
{
    let a: 10 = 11; // error
    let b = 11;     // ok
    b = 10;         // ok

    print("done.");
}

Modern Syntax

No main function required

Top-level statements run directly; no main is needed.

const arr = [1, 2, 3, 4, 5];
for (const b of arr)
    print(b);

Logical assignments

Supports ??=, ||=, and &&=.

function foo1(f?: (a: number) => number) {
    f ??= ((a: number) => a)
    f(42);
}

function foo2(f?: (a: number) => number) {
    f ||= ((a: number) => a)
    f(42);
}

function foo3(f?: (a: number) => number) {
    f &&= ((a: number) => a)
    f(42);
}

function main() {
    foo1();
    foo2();
    foo3((a: number) => a * 2);
}

Optional tuple elements

function main() {
    type StaffAccount = [number, string, string, string?];

    const staff: StaffAccount[] = [
        [0, "Adankwo", "adankwo.e@"],
        [1, "Kanokwan", "kanokwan.s@"],
        [2, "Aneurin", "aneurin.s@", "Supervisor"],
    ];

    for (const v of staff) print(v[0], v[1], v[2], v[3] || "<no value>");

    assert(staff[2][3] == "Supervisor");

    print("done.");
}

Explicit resource management (using)

A using declaration disposes the resource via Symbol.dispose when the scope exits.

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");
    }
}

Advanced Patterns

Union types in yield

yield* can delegate to a generator yielding a union of types.

function* g() {
  yield* (function* () {
    yield 1.0;
    yield 2.0;
    yield "3.0";
    yield 4.0;
  })();
}

function main() {
    for (const x of g())
        if (typeof x == "string")
            print("string: ", x);
        else if (typeof x == "number")
            print("number: ", x);
}

Well-known symbols

Symbol.toPrimitive

const object1 = {

    [Symbol.toPrimitive](hint: string) : string | number | Boolean {
        if (hint === "number") {
            return 10;
        }
        if (hint === "string") {
            return "hello";
        }
        return true;
    }

};

print(+object1);      // 10      hint is "number"
print(`${object1}`);  // "hello" hint is "string"
print(object1 + "");  // "true"  hint is "default"

Symbol.iterator

class StringIterator {
    next() {
        return {
            done: true,
            value: ""
        };
    }
    [Symbol.iterator]() {
        return this;
    }
}

function main() {
    for (const v of new StringIterator) { }
}

Compilation & Modules

Emit an executable (--emit=exe)

tsc --opt --emit=exe <file>.ts

Shared libraries with import

Export functions from a shared library and import them by path. The path can point to a .ts source file or to a .dll compiled with tsc --emit=dll shared_lib.ts.

shared_lib.ts — the shared library:

export function test1()
{
    print("Hello World!");
}

Consuming it:

// './shared_lib' can resolve to shared_lib.ts or shared_lib.dll
import './shared_lib'

function main()
{
    test1();
}

Loading a shared library at runtime

function LoadFunction(dllName: string, funcName: string)
{
    LoadLibraryPermanently(dllName);
    return SearchForAddressOfSymbol(funcName);
}

let test1: () => void = LoadFunction("./shared_lib.dll", "test1");

function main()
{
    test1();
}

Debug information (--di)

tsc --opt_level=0 --di --emit=obj <file>.ts