Define TypeScript Static Methods

Recently, I was working on a TypeScript project where I needed to implement utility functions that didn’t require an instance of a class.

As a solution for this, I decided to use the TypeScript static methods. To build TypeScript applications and write more efficient, organized code, understanding static methods is essential.

In this article, I’ll explain what static methods are in TypeScript. Then, with the help of real-time examples, we discuss how to define TypeScript static methods.

What Are Static Methods in TypeScript?

Static methods are class methods that belong to the class itself rather than to instances of the class. You can call them directly on the class without creating an object first. They’re perfect for utility functions that don’t need access to instance-specific data.

Unlike regular methods that can access instance properties using this, static methods can only access static properties and other static methods of the class.

Creating Static Methods in TypeScript

To define a static method in TypeScript, you simply add the static keyword before the method name. Here’s a basic example:

class Calculator {
  static add(a: number, b: number): number {
    return a + b;
  }
}

// Call the static method directly on the class
const sum = Calculator.add(5, 3);  // Returns 8
console.log(sum);

Output:

Define static methods in TypeScript

Notice how I’m calling add() directly on the Calculator class without creating an instance first.

Check out: Iterate Over Objects in TypeScript

When to Use Static Methods in TypeScript

There are several scenarios where static methods make perfect sense:

1. Utility Functions

Static methods are ideal for utility functions that perform operations that don’t depend on instance data:

class StringUtils {
  static capitalize(str: string): string {
    if (!str) return str;
    return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
  }

  static reverse(str: string): string {
    return str.split('').reverse().join('');
  }
}

// Usage
const name = StringUtils.capitalize("john");  // "John"
const reversed = StringUtils.reverse("Hello");  // "olleH"

2. Factory Methods

Static methods work great as factory methods that create and return new instances:

class User {
  private name: string;
  private email: string;
  private role: string;

  constructor(name: string, email: string, role: string) {
    this.name = name;
    this.email = email;
    this.role = role;
  }

  static createAdmin(name: string, email: string): User {
    return new User(name, email, "admin");
  }

  static createGuest(): User {
    return new User("Guest", "guest@example.com", "guest");
  }
}

// Usage
const admin = User.createAdmin("Alice", "alice@example.com");
const guest = User.createGuest();

3. Configuration and Constants

Static methods can provide access to configuration options:

class Config {
  private static apiUrl: string = "https://api.example.com";
  private static timeout: number = 3000;

  static getApiUrl(): string {
    return Config.apiUrl;
  }

  static setTimeout(timeout: number): void {
    Config.timeout = timeout;
  }

  static getTimeout(): number {
    return Config.timeout;
  }
}

// Usage
console.log(Config.getApiUrl());  // "https://api.example.com"
Config.setTimeout(5000);
console.log(Config.getTimeout());  // 5000

Static Methods vs. Instance Methods in TypeScript

To understand the difference, let’s look at a practical example:

class TaxCalculator {
  // Static property
  static taxRate: number = 0.07;

  // Instance property
  itemPrice: number;

  constructor(itemPrice: number) {
    this.itemPrice = itemPrice;
  }

  // Static method
  static calculateTax(price: number): number {
    return price * TaxCalculator.taxRate;
  }

  // Instance method
  getTotalPrice(): number {
    return this.itemPrice + TaxCalculator.calculateTax(this.itemPrice);
  }
}

// Using static method
const taxAmount = TaxCalculator.calculateTax(100);  // $7
console.log(`Tax: $${taxAmount}`);

// Using instance method
const calculator = new TaxCalculator(100);
const total = calculator.getTotalPrice();  // $107
console.log(`Total: $${total}`);

In this example, I can calculate the tax on any price using the static calculateTax() method without creating an instance. But to get the total price of an item, I need to create a TaxCalculator instance.

Check out: How to Handle Catch Error Types in TypeScript?

Accessing Static Properties Within Static Methods

Static methods can access static properties, but not instance properties:

class DateUtils {
  static defaultFormat: string = "MM/DD/YYYY";

  static formatDate(date: Date, format?: string): string {
    const actualFormat = format || DateUtils.defaultFormat;

    // Implementation would go here
    return actualFormat === "MM/DD/YYYY" 
      ? `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`
      : date.toISOString();
  }
}

// Usage
const daytoday = new Date();
console.log(DateUtils.formatDate(daytoday));  // "6/16/2025" (example)
console.log(DateUtils.formatDate(daytoday, "ISO"));  // "2025-06-16T13:36:44.867Z"

Output:

Static Methods in TypeScript

Static Methods with Inheritance

Subclasses inherit static methods:

class Vehicle {
  static getVehicleType(): string {
    return "Generic Vehicle";
  }

  static createVehicle(): Vehicle {
    return new Vehicle();
  }
}

class Car extends Vehicle {
  static getVehicleType(): string {
    return "Car";
  }

  static createVehicle(): Car {
    return new Car();
  }
}

console.log(Vehicle.getVehicleType());  // "Generic Vehicle"
console.log(Car.getVehicleType());  // "Car"

const vehicle = Vehicle.createVehicle();  // Vehicle instance
const car = Car.createVehicle();  // Car instance

Output:

Static Methods With Inheritance in TypeScript

Notice that the static methods are overridden in the Car class, not overloaded.

Advanced Uses of Static Methods

Singleton Pattern

The Singleton pattern ensures a class has only one instance. Static methods play a crucial role in implementing this pattern:

class Database {
  private static instance: Database | null = null;
  private connectionString: string;

  private constructor(connectionString: string) {
    this.connectionString = connectionString;
    console.log(`Connected to database: ${connectionString}`);
  }

  static getInstance(connectionString: string): Database {
    if (!Database.instance) {
      Database.instance = new Database(connectionString);
    }
    return Database.instance;
  }

  query(sql: string): void {
    console.log(`Executing query: ${sql}`);
  }
}

// Usage
const db1 = Database.getInstance("mongodb://localhost:27017");
const db2 = Database.getInstance("mongodb://localhost:27017");

console.log(db1 === db2);  // true - they are the same instance

db1.query("SELECT * FROM users");

Output:

Advanced Uses of Static Methods in TypeScript

Check out: Optional Parameters in TypeScript Interfaces

Static Method Chaining

You can chain static methods for a fluent interface:

class QueryBuilder {
  private static query: string = "";

  static select(fields: string[]): typeof QueryBuilder {
    QueryBuilder.query = `SELECT ${fields.join(", ")}`;
    return QueryBuilder;
  }

  static from(table: string): typeof QueryBuilder {
    QueryBuilder.query += ` FROM ${table}`;
    return QueryBuilder;
  }

  static where(condition: string): typeof QueryBuilder {
    QueryBuilder.query += ` WHERE ${condition}`;
    return QueryBuilder;
  }

  static build(): string {
    const finalQuery = QueryBuilder.query;
    QueryBuilder.query = "";  // Reset for next use
    return finalQuery;
  }
}

// Usage
const query = QueryBuilder
  .select(["id", "name", "email"])
  .from("users")
  .where("age > 21")
  .build();

console.log(query);  // "SELECT id, name, email FROM users WHERE age > 21"

Output:

Static method chaining in TypeScript

I find this pattern extremely useful when building complex objects or queries.

Check out: Conditionally Add Property to Object in TypeScript

TypeScript Static Methods vs. Module Functions

Sometimes you might wonder whether to use static methods or just functions in a module. Here’s a quick comparison:

Static methods:

  • Encapsulate related functionality within a class
  • Can access private static members of the class
  • Can be inherited and overridden
  • Perfect for object-oriented designs

Module functions:

  • Simpler to import and use
  • No need for class syntax
  • May be more appropriate for pure functional programming

Conclusion

By using the above-explained static methods, you can write more maintainable and efficient TypeScript code. Just remember their key characteristics: they belong to the class, not instances; they can only access static properties; and they’re called directly on the class itself.

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.