# TypeScript Generics

Generics allow you to create reusable components that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types while maintaining type safety.

## 1. The Problem

Without generics, we would either have to give a specific type to a function or use `any`.

```typescript
// Specific type: Not reusable for numbers
function identity(arg: string): string {
    return arg;
}

// Any: We lose information about what that type was when the function returns
function identity(arg: any): any {
    return arg;
}
```

## 2. Generic Syntax

We use a **type variable**, usually denoted as `<T>`, to capture the type the user provides (e.g., `number` or `string`).

```typescript
function identity<T>(arg: T): T {
    return arg;
}
```

Now we can call it in two ways:

```typescript
// 1. Explicitly passing the type
let output = identity<string>("myString");

// 2. Type Argument Inference (Compiler figures it out)
let output2 = identity("myString");
```

## 3. Generic Interfaces

You can define interfaces that accept type arguments.

```typescript
interface Box<T> {
    contents: T;
}

let stringBox: Box<string> = { contents: "Hello" };
let numberBox: Box<number> = { contents: 42 };
```

## 4. Generic Classes

Classes can also be generic.

```typescript
class KeyValuePair<K, V> {
    constructor(public key: K, public value: V) {}
}

let pair = new KeyValuePair<number, string>(1, "a");
```

## 5. Generic Constraints

Sometimes you want to restrict the types that can be used with a generic. For example, if you want to access `.length`, you need to constrain `T` to types that have a `.length` property.

```typescript
interface Lengthwise {
    length: number;
}

// T must extend Lengthwise
function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length); // Now we know it has a .length property, so no error
    return arg;
}

loggingIdentity({ length: 10, value: 3 }); // OK
// loggingIdentity(3); // Error, number doesn't have .length
```

[[programming/javascript/typescript/typescript]]