TypeScript Static Properties and Methods

Note: If you're new to TypeScript, check our Getting Started with TypeScript tutorial first.


In TypeScript, the static keyword is used to create static properties and methods.

Static properties and methods belong to the class itself, and not to any individual instances of the class. In other words, they are shared among all instances of the class.

Static properties and methods are useful for data or behavior that is common to all instances.


TypeScript Static Properties

To create a static property, we use the static keyword before the property name. For example,

class Dog {
    // Declare a static property
    static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }
}

// Create instances of Dog class
let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

// Access the static property outside the class
console.log(`All dogs say ${Dog.bark}`);

Output

Wolfie loves its owner, Jessica, and says Woof!
Honey loves its owner, James, and says Woof!
All dogs say Woof!

Here, we have created a static property bark inside the Dog class. Thus, a single copy of bark is shared by all instances of Dog.

On the other hand, each instance of Dog will have its own copy of non-static properties and methods, i.e., name, owner, and dogIntro().

All Instances Share a Static Property
All Instances Share a Static Property

Static Properties Are Accessed Using the Class Name

In the previous example, notice how the static property is accessed both inside and outside the class:

class Dog {
    ... ... ...

    // Access the static property inside the class    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }
}

... ... ...

// Access the static property outside the class
console.log(`All dogs say ${Dog.bark}`);

Usually, we use this to access non-static properties inside the class, while we use the object name (dog1 or dog2) to access those properties outside the class.

However, we use the class name to access static properties since they belong to the class itself, rather than to individual instances of the class:

// Valid way to access static property
Dog.bark

// Invalid ways to access static property (inside class)
this.bark

// Invalid ways to access static property (outside class)
dog1.bark
dog2.bark

Note: You can use this to access static properties inside a static method.


Example 1: TypeScript Static Properties

class Employee {
    static headcount: number = 0; // Static property

    constructor(private name: string, private jobTitle: string) {
        // Increment headcount whenever a new instance is created
        Employee.headcount++;
    }
    
    getInfo(): void {
        console.log(`Employee: ${this.name}`);
        console.log(`Job Title: ${this.jobTitle}\n`);
    }
}

let employee1 = new Employee("John Doe", "Developer");
let employee2 = new Employee("Jane Doe", "Designer");

// Print the employee details
employee1.getInfo();
employee2.getInfo();

// Print the static property
console.log(`Headcount: ${Employee.headcount}`);

Output

Employee: John Doe
Job Title: Developer

Employee: Jane Doe
Job Title: Designer

Headcount: 2

In this program, we've created a static property headcount that is incremented each time we create an instance of the Employee class.

Initially, the value of headcount is 0.

And since we then proceeded to create two Employee instances (employee1 and employee2), the final value of headcount is 2.


TypeScript Static Methods

Like static properties, static methods belong to the class itself rather than to individual instances.

To create a static method, we use the static keyword before the method name. For example,

class Dog {
    private static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }

    // Create a static method that returns the static property
    static getBark(): string {
        return Dog.bark;
    }
}

// Create instances of Dog class
let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

// Access the static method
let dogBark: string = Dog.getBark();

console.log(`All dogs say ${dogBark}`);

Output

Wolfie loves its owner, Jessica, and says Woof!
Honey loves its owner, James, and says Woof!
All dogs say Woof!

Here, the static method getBark() returns the value of the private static property bark.

Outside the class, we accessed the static method by using the class name instead of the objects dog1 or dog2:

// Access the static method
let dogBark: string = Dog.getBark();

Example 2: TypeScript Static Methods

class Circle {

    // Static constant
    static readonly PI: number = 3.14159;

    static calculateArea(radius: number): number {
        return Circle.PI * radius * radius;
    }
}

// Access static property
console.log(`Value of PI: ${Circle.PI}`);

// Access static method
let area: number = Circle.calculateArea(5);
console.log(`Area of Circle: ${area}`);

Output

Value of PI: 3.14159
Area of Circle: 78.53975

Here, PI is a static constant, and calculateArea() is a static method. Thus, they're both shared by all instances of the Circle class.

Note: We use the readonly access modifier to declare class properties as constants. On the other hand, the const keyword is used to declare normal variables as constants.


More on TypeScript static

Static properties and methods can be accessed without creating any instances.

Since static properties and methods belong to the class itself, they don't depend on the existence of class instances.

As a result, they can be accessed even if you haven't created any instance of the class. For example,

class Dog {
    static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}.`;
    }

    // Use 'this' inside a static method
    static getBark(): string {
        return Dog.bark;
    }
}

// Access static property
console.log(`Say ${Dog.bark}`);

// Access static method
let dogBark: string = Dog.getBark();
console.log(`All dogs say ${dogBark}`);

Output

Say Woof!
All dogs say Woof!

Here, we accessed the static property and method without creating any instance of Dog.

However, we cannot access non-static properties and methods without creating an instance.

// Error: Property 'dogIntro' does not exist on type 'typeof Dog'.
console.log(Dog.dogIntro());
Within static methods, 'this' refers to the class and not to the instance.

1. 'this' in Non-Static Methods

When you use this inside non-static methods, it refers to the individual instance of the class. For example,

class Dog {
    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}.`;
    }
}

let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

// Output:
// Wolfie loves its owner, Jessica.
// Honey loves its owner, James.

When dog1 is created.

  • this.name refers to dog1.name.
  • this.owner refers to dog1.owner.

When dog2 is created.

  • this.name refers to dog2.name.
  • this.owner refers to dog2.owner.

2. 'this' in Static Methods

However, inside static methods, this refers to the class itself, and not to any individual instances. For example,

class Dog {
    private static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}.`;
    }

    // Use 'this' inside a static method
    static getBark(): string {
        return this.bark;
    }
}

let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

let dogBark: string = Dog.getBark();
console.log(`All dogs say ${dogBark}`);

Output

Wolfie loves its owner, Jessica.
Honey loves its owner, James.
All dogs say Woof!

Here, we've used this inside the static method getBark():

static getBark(): string {
    return this.bark;
}

In this case, it doesn't matter what or how many instances of Dog you create. In all cases, this.bark will always refer to Dog.bark since it's used inside a static method.

Static methods cannot access non-static properties.

Static methods can't access non-static properties because non-static properties belong to individual instances of a class.

As such, non-static properties don't come into existence until an object is created. For example,

class Dog {

    // Non-static property
    breed: string;

    constructor(breed: string) {
        this.breed = breed;
    }

    // Static method
    static getBreed(): void {
    
        // Error because getBreed() is static but breed is not
        console.log(this.breed);
    }
}

Here, the static method getBreed() cannot access the non-static property breed because this inside static methods refers to the class and not to the instance of the class.

However, breed (as a non-static property) belongs to class instances. Thus, getBreed() is unable to access it.

Non-static methods can access static properties.

While static methods cannot access non-static properties, non-static methods can easily access static properties. For example,

class Dog {
    // Declare a static property
    static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    // Non-static method that accesses
    // both static and non-static properties
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }
}

let dog1 = new Dog("Wolfie", "Jessica");
console.log(dog1.dogIntro());

// Output: Wolfie loves its owner, Jessica, and says Woof!

Here, the non-static dogIntro() method is able to access the static property bark.

It's because instance methods have access to this (the instance) and can also access static members using the class name (Dog.bark).

This is allowed because static members are accessible on the class itself.


Read More:

Did you find this article helpful?

Our premium learning platform, created with over a decade of experience and thousands of feedbacks.

Learn and improve your coding skills like never before.

Try Programiz PRO
  • Interactive Courses
  • Certificates
  • AI Help
  • 2000+ Challenges