Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A class expression is a syntax for defining a class within an expression context rather than as a standalone statement. Unlike class declarations, class expressions are evaluated at runtime, are not hoisted to the top of their lexical scope, and can be either anonymous or named. In TypeScript, class expressions fully support the language’s static typing features, including access modifiers, generics, and interface implementations.

Anonymous Class Expressions

When a class expression is anonymous, the class does not have an internal identifier. The variable it is assigned to becomes the binding used to instantiate it.
const Point = class {
    public x: number;
    public y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    public getCoordinates(): [number, number] {
        return [this.x, this.y];
    }
};

const p = new Point(10, 20);

Named Class Expressions

A class expression can include an identifier. This identifier is strictly local to the class’s own body and is not injected into the enclosing lexical scope. It is typically used for self-reference or recursion within the class.
const Task = class TaskImpl {
    public isComplete: boolean = false;

    public getClassName(): string {
        // TaskImpl is accessible here
        return TaskImpl.name; 
    }
};

// TaskImpl is undefined in this outer scope
// const t = new TaskImpl(); // Error: Cannot find name 'TaskImpl'
const t = new Task();

Generic Class Expressions

Class expressions can declare type parameters exactly like class declarations. The type parameters are defined immediately following the class keyword (or the class name, if named).
const Container = class <T> {
    private _value: T;

    constructor(value: T) {
        this._value = value;
    }

    public getValue(): T {
        return this._value;
    }
};

const stringContainer = new Container<string>("TypeScript");

Implementing Interfaces and Extending Classes

Class expressions can participate in inheritance chains and interface contracts using the extends and implements keywords.
interface Loggable {
    log(): void;
}

class BaseEntity {
    constructor(public id: string) {}
}

const UserEntity = class extends BaseEntity implements Loggable {
    constructor(id: string, public username: string) {
        super(id);
    }

    public log(): void {
        console.log(`User: ${this.username} (${this.id})`);
    }
};

Type Inference and Instance Types

When you assign a class expression to a variable, TypeScript infers the variable’s type as the constructor function of that class. Unlike class declarations, assigning a class expression to a variable only creates a value in the value space. It does not automatically create a corresponding type in the type space. Attempting to use the variable directly as a type (e.g., let c: Config) will throw the TypeScript error: 'Config' refers to a value, but is being used as a type here. To extract the instance type of a class expression, you must use the InstanceType utility type in conjunction with the typeof operator. The typeof operator extracts the constructor type, and InstanceType resolves that constructor type to its corresponding instance type.
const Config = class {
    public timeout: number = 3000;
};

// 'Config' is only a value. 
// let c: Config; // Error: 'Config' refers to a value, but is being used as a type here.

// typeof Config extracts the constructor type.
// InstanceType<typeof Config> extracts the instance type.
type ConfigInstance = InstanceType<typeof Config>;

const myConfig: ConfigInstance = new Config();
Master TypeScript with Deep Grasping Methodology!Learn More