# TypeScript Advanced Types

TypeScript offers powerful features to manipulate types based on other types. This guide covers **Mapped Types** and **Conditional Types**, which are essential for creating flexible and reusable type definitions.

## 1. Mapped Types

Mapped types allow you to create new types by iterating over the properties of an existing type. This is similar to using `.map()` on an array but for types.

### Basic Syntax

The syntax uses the `in` keyword to iterate over keys.

```typescript
type OptionsFlags<Type> = {
  [Property in keyof Type]: boolean;
};

type FeatureFlags = {
  darkMode: () => void;
  newUserProfile: () => void;
};

// Result: { darkMode: boolean; newUserProfile: boolean; }
type FeatureOptions = OptionsFlags<FeatureFlags>;
```

### Modifiers

You can add or remove modifiers like `readonly` or `?` (optional) using `+` or `-`.

```typescript
// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
  -readonly [Property in keyof Type]: Type[Property];
};

type LockedAccount = {
  readonly id: string;
  readonly name: string;
};

// Result: { id: string; name: string; } (no longer readonly)
type UnlockedAccount = CreateMutable<LockedAccount>;
```

## 2. Conditional Types

Conditional types look like ternary operators in JavaScript. They allow you to choose a type based on a condition.

### Syntax

```typescript
SomeType extends OtherType ? TrueType : FalseType;
```

### Example

```typescript
interface Animal {
  live(): void;
}
interface Dog extends Animal {
  woof(): void;
}

type Example1 = Dog extends Animal ? number : string;
// type Example1 = number

type Example2 = RegExp extends Animal ? number : string;
// type Example2 = string
```

## 3. The `infer` Keyword

Within a conditional type, you can use the `infer` keyword to declare a type variable to be inferred (deduced) from within the condition. This is commonly used to extract return types or argument types.

### Example: Extracting Return Type

```typescript
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
  ? Return
  : never;

type Num = GetReturnType<() => number>;
// type Num = number
```

[[programming/javascript/typescript/typescript]]