TypeScript Generic Classes (original) (raw)

Last Updated : 15 Sep, 2025

Generics in TypeScript allow us to create reusable and type-safe components. Generic classes define a blueprint that can work with multiple data types without sacrificing type safety.

**Syntax:

class GenericClass { constructor(private value: T) {} getValue(): T { return this.value; } }

**In the above syntax:

**Example 1: Basic Generic Class

A simple generic class that can hold values of different types while ensuring type safety.

JavaScript `

class Box { private content: T;

constructor(content: T) {
    this.content = content;
}

getContent(): T {
    return this.content;
}

}

const numBox = new Box(100); console.log("Number Content:", numBox.getContent());

const strBox = new Box("Hello, TypeScript Generics!"); console.log("String Content:", strBox.getContent());

`

**Output:

Number Content: 100 String Content: Hello, TypeScript Generics!

**In this example:

**Example 2: Using Generic Constraints in Classes

Constraints in generics restrict the types that can be used as type parameters.

JavaScript `

class Box { private value: T;

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

double(): number {
    return this.value * 2;
}

}

const numBox = new Box(10); console.log("Double Value:", numBox.double());

`

**Output:

Double Value: 20

**In this example:

**Example 3: Multiple Type Parameters in Generic Classes

A generic class can accept multiple type parameters to manage different data types simultaneously.

JavaScript `

class Pair<K, V> { private key: K; private value: V;

constructor(key: K, value: V) {
    this.key = key;
    this.value = value;
}

getKey(): K {
    return this.key;
}

getValue(): V {
    return this.value;
}

}

const userPair = new Pair<number, string>(1, "John Doe"); console.log("Key:", userPair.getKey(), "Value:", userPair.getValue());

`

**Output:

Key: 1 Value: John Doe

**In this example:

**Example 4: Generic Classes with Static Properties

Static properties belong to the class itself and cannot be generic, but they can be used alongside generic class instances.

JavaScript `

class Counter { private value: T; static count: number = 0;

constructor(value: T) {
    this.value = value;
    Counter.count++; 
}

static getCount(): number {
    return Counter.count;
}

}

const obj1 = new Counter(10); const obj2 = new Counter("Hello");

console.log("Total Instances Created:", Counter.getCount());

`

**Output:

Total Instances Created: 2

**In this example:

Types of Generic Classes

TypeScript supports different variations of generic classes based on their structure and constraints.

1. Single Type Parameter Generic Class

A generic class that works with a single type parameter. It is the most commonly used generic class type, allowing flexibility while ensuring type safety. It provides better code maintainability by reducing redundant type-specific implementations.

JavaScript `

class Container { private item: T; constructor(item: T) { this.item = item; } getItem(): T { return this.item; } }

`

2. Multiple Type Parameters Generic Class

A class that supports multiple type parameters, allowing it to store two different types. This is useful when dealing with key-value pairs, mapping relationships, or associating different data types together in a structured manner.

JavaScript `

class KeyValue<K, V> { constructor(public key: K, public value: V) { } }

`

3. Bounded Generic Class

A class that restricts type parameters using constraints to ensure that only specific types are allowed.

JavaScript `

class Num { private num: T; constructor(num: T) { this.num = num; } double(): number { return this.num * 2; } }

`

4. Generic Class with Default Type

A generic class that assigns a default type when none is specified. This helps ensure a default behavior without requiring explicit type declaration every time.

JavaScript `

class Default<T = string> { private item: T; constructor(item: T) { this.item = item; } getItem(): T { return this.item; } }

`

5. Recursive Generic Class

A generic class that references itself, useful in implementing linked lists or tree structures. It allows nodes to link to other nodes of the same type, enabling dynamic data structures.

JavaScript `

class Processor<T = any> { process(item: T): void { console.log("Processing:", item); } }

`