TypeScript
Completed
-
Section 1: Getting Started
-
Section 2: Basic Types
-
Section 3: Functions and Objects
-
Section 4: Advanced Types
-
Section 5: Object-Oriented TypeScript
-
Section 6: Working with Modules
-
Section 7: Tooling and Practice
-
Section 8: Type-Level Programming
-
Section 9: TypeScript with Backends
-
Section 10: Testing Typed Code
-
Section 11: Data Validation with Types
-
Section 12: Practical Projects
-
Section 13: Compiler Internals
-
Section 14: Configuration Deep Dive
-
Section 15: Enums, Symbols, and Special Types
-
Section 16: Working with Async Code
-
Section 17: TypeScript and the DOM
-
Section 18: Advanced Generics Practice
-
Section 19: Working with Third-Party Types
-
Section 20: Monorepo and Large-Scale Practices
-
Section 21: Common Pitfalls and Best Practices
-
Section 22: Interview Practice
-
Section 23: Handbook: Narrowing In Depth
-
Section 24: Handbook: Object Types In Depth
-
Section 25: Handbook: Classes In Depth
-
Section 26: Handbook: Modules In Depth
-
Section 27: Handbook: Declaration Files In Depth
-
Section 28: JSX and Namespaces
-
Section 29: Compiler Configuration Reference
-
Section 30: More Practice Exercises
-
Section 31: Handbook: Everyday Types Deep Dive
-
Section 32: Utility Types Full Reference
-
Section 33: Decorators Reference
-
Section 34: Mixins and Advanced OOP Patterns
-
Section 35: Iterators and Generators Typing
-
Section 36: More Type-Level Programming Practice
-
Section 37: TypeScript Ecosystem Tools
-
Section 38: TypeScript with Testing Frameworks
-
Section 39: TypeScript for Library Authors
-
Section 40: More Interview Practice
-
Section 41: Handbook: Functions In Depth
-
Section 42: Handbook: Type Manipulation Deep Dive
-
Section 43: More Real-World Patterns
-
Section 44: TypeScript Release Notes Highlights
-
Section 45: Final Practice and Review
150: Static Members and Static Blocks
Imagine you're running a professional kitchen. You have several chefs (these are your instances). Each chef has their own personal set of knives and their own specific station. But in the middle of the kitchen, there's one giant, shared chalkboard that lists the "Daily Specials."
The chalkboard isn't "owned" by Chef Mario or Chef Sarah; it belongs to the Kitchen itself. If Chef Mario updates the special from "Salmon" to "Trout," Chef Sarah sees that change immediately because they are both looking at the same board. Furthermore, the act of scrubbing that chalkboard clean every morning happens once, before any chef even clocks in for their shift.
In TypeScript, that chalkboard is a static member, and the morning cleaning routine is a static block.
Belonging to the Class, Not the Instance
Usually, when you define a property in a class, you're describing what every individual object created from that class will have. But sometimes, you need data that is global to the class itself. By adding the static keyword, you're telling TypeScript: "This doesn't belong to the objects; it belongs to the blueprint."
Take a look at this GameSession example. We want to track how many players are currently online across the entire game, regardless of which specific session object we are interacting with.
class GameSession {
static totalPlayersOnline: number = 0; // The "Chalkboard"
public playerName: string; // The "Chef's Knife"
constructor(name: string) {
this.playerName = name;
GameSession.totalPlayersOnline++; // We access it via the Class name, not 'this'
}
static getGlobalStatus() {
return `There are currently ${GameSession.totalPlayersOnline} players in the world.`;
}
}
const player1 = new GameSession("Alice");
const player2 = new GameSession("Bob");
console.log(GameSession.totalPlayersOnline); // 2
console.log(GameSession.getGlobalStatus()); // "There are currently 2 players in the world."
Notice that I didn't call player1.getGlobalStatus(). If I tried, TypeScript would throw an error. Why? Because the method isn't on the player; it's on the GameSession class. I've found that beginners often trip up here by trying to use this inside a static method to access instance properties. You can't do that—the static method has no idea which "player" you're talking about.
Doing the Heavy Lifting Before the First Instance
Sometimes, initializing a static property isn't as simple as = 0. You might need to read a config file, parse a JSON string, or run a complex loop to set up your static data. This is where static blocks come in.
A static block runs exactly once: the moment the class is first loaded into memory. It's the perfect place for that "morning cleaning routine" I mentioned earlier.
class DatabaseConnection {
static connectionString: string;
static isReady: boolean = false;
// This is the static block
static {
console.log("Initializing system settings...");
const env = "production"; // Imagine this coming from process.env
if (env === "production") {
this.connectionString = "https://prod-db.example.com";
} else {
this.connectionString = "https://localhost:5432";
}
this.isReady = true;
}
static connect() {
return `Connecting to ${this.connectionString}...`;
}
}
// The static block runs the moment we touch the class
console.log(DatabaseConnection.connect());
I really like static blocks because they keep the initialization logic out of the constructor. Since the constructor runs every time you call new, putting global setup logic there would be a performance nightmare (and logically incorrect). The static block ensures the "chalkboard" is prepared once, and only once.
📋 Practical Task
Build a Global Application Configuration Manager
Your task is to create a ConfigManager class that handles application settings. This class should not be instantiated (you don't need to use new), but instead should act as a single source of truth for the app.
- Create a static property called
settings(a record or object) and a static property calledinitialized(boolean). - Implement a static block that simulates loading a configuration. Inside the block, set
initializedtotrueand populatesettingswith at least two values:theme(e.g., "dark") andapiEndpoint(e.g., "https://api.myapp.com"). - Create a static method called
getConfig(key: string)that returns the value for the given key from thesettingsobject. - Verify your implementation by calling
ConfigManager.getConfig("theme")and logging the result to the console.
There are no comments for now.