# TypeScript Conditional Types

Conditional types allow you to define types that depend on other types. They take a form that looks like a ternary operator in JavaScript.

## 1. Syntax

```typescript
SomeType extends OtherType ? TrueType : FalseType;
```

If `SomeType` is assignable to `OtherType`, then the type resolves to `TrueType`, otherwise it resolves to `FalseType`.

## 2. Basic Usage

```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. Distributive Conditional Types

When conditional types act on a generic type, they become **distributive** when given a union type. This means the condition is applied to each member of the union individually.

```typescript
type ToArray<Type> = Type extends any ? Type[] : never;

type StrArrOrNumArr = ToArray<string | number>;
// Result: string[] | number[]
```

If we didn't want this distribution, we would wrap the `extends` keywords in square brackets:

```typescript
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
type StrOrNumArr = ToArrayNonDist<string | number>;
// Result: (string | number)[]
```

## 4. Filtering Types (Exclude/Extract)

Conditional types are often used to filter unions by returning `never` for types you want to remove. Since `never` is ignored in unions, this effectively removes the type.

```typescript
// Exclude null and undefined from T
type MyNonNullable<T> = T extends null | undefined ? never : T;

type T0 = MyNonNullable<string | number | undefined>;
// type T0 = string | number
```

This is how the built-in `Exclude<T, U>` utility type works:

```typescript
type MyExclude<T, U> = T extends U ? never : T;

type T1 = MyExclude<"a" | "b" | "c", "a">;
// "b" | "c"
```

## 5. Inferring Within Conditional Types (`infer`)

You can use the `infer` keyword to deduce a type within the condition. This is useful for unwrapping types (like getting the return type of a function or the element type of an array).

```typescript
type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;

type Str = Flatten<string[]>;
// type Str = string

type Num = Flatten<number>;
// type Num = number
```

[[programming/javascript/typescript/typescript]]