# Enums

A helpful addition to the standard set of datatypes from JavaScript is the `enum`. An enum is a way of giving more friendly names to sets of *enumerable* values. It also allows us to validate a value against a set of predefined values.

TypeScript provides both numeric and string-based enums.

## Numeric enums

```typescript
enum Fruit {
  Orange,
  Banana,
  Apple,
}

let myFruit: Fruit;

// A value gets assigned to myFruit...

if (myFruit === Fruit.Orange) {
  console.log("I'm eating an orange!");
} else if (myFruit === Fruit.Banana) {
  console.log("I'm eating a banana!");
} else if (myFruit === Fruit.Apple) {
  console.log("I'm eating an apple!");
}
```

In this example, we've defined a list of fruit in the `Fruit` enum. We then create a variable named `myFruit` and the user assigns a value to `myFruit` by selecting one of the fruit possibilities.

The reason this works is because the enum is actually assigning a zero-based index to all of the defined values. Therefore the comparison is being made between two numeric values. In fact, if we don't want the numbers to start at zero, we can override the sequence like so:

```typescript
enum Fruit {
  Orange = 1,
  Banana, // 2
  Apple, // 3
}
```

Now our fruit indices start at `1`.

We can actually assign any numeric value, and the following items will follow incrementally:

```typescript
enum Fruit {
  Orange, // 0
  Banana = 572,
  Apple, // 573
}
```

But what if we don't want incremental values? Well, we can assign a value to each item in the list:

```typescript
enum Keycodes {
  UP = 38,
  DOWN = 40,
  LEFT = 37,
  RIGHT = 39,
  ENTER = 13,
  ESCAPE = 27,
  SPACE = 32,
}
```

## String enums

In a string enum, each member has to be constant-initialized with a string literal, or with another string enum member.

```typescript
enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}
```

String enums don’t have auto-incrementing behavior. A benefit of string enums is that they will usually have a meaningful and readable value at runtime, independent of the name of the enum member itself. Whereas, numeric enums have values that may be difficult to decipher at runtime.

Consider another example:

```typescript
enum CurrencySymbols {
  USD = '$',
  EUR = '€',
  JPY = '¥',
  GBP = '£',
}

function formatMoney(amount: number, currencySymbol: CurrencySymbols) {
  return `${currencySymbol}${amount}`;
}

formatMoney(100, CurrencySymbols.USD); // $100
formatMoney(100, CurrencySymbols.JPY); // ¥100
```

Here we have a naïve money formatter function, `formatMoney`. It takes two parameters: `amount`, which is a `number`, and `currencySymbol` which accepts values of type `CurrencySymbols`.

If we attempt to pass a currency that isn't included in the enum, we will expect an error:

```typescript
formatMoney(100, CurrencySymbols.CAD); // Error: 'CAD' does not exist on type 'typeof CurrencySymbols'.
```
