# Type guards

Normally in JavaScript, when we're unsure of a value's type, we check the existance of one of its members to determine what it is:

```typescript
function getID(): string | number {
    return Math.random() > 0.5 ? "1" : 1;
}

let id = getID();

if (id.toUpperCase) {
    id = id.toUpperCase();
} else if (id.toFixed) {
    id = id.toFixed();
}
```

This code will throw the following TypeScript errors:

`Property 'toUpperCase' does not exist on type 'string | number'` `Property 'toUpperCase' does not exist on type 'number'` `Property 'toFixed' does not exist on type 'string | number'` `Property 'toFixed' does not exist on type 'string'`

We're getting these errors because we can only access members common to all types in a union, which `id` is. So, since `id` could be a `string` or a `number`, and since neither of the two share the `toUpperCase` or `toFixed` members, we get those errors.

If, however, we wanted to run `id.toString()`, we'd be fine, since both `number` and `string` have the `toString` method.

If we assert, however, that what we're checking is a `string` or a `number`, then we eliminate the errors:

```typescript
// ...
if ((<string>id).toUpperCase) {
    id = (<string>id).toUpperCase();
} else if ((<number>id).toFixed) {
    id = (<number>id).toFixed();
}
```

Now that we've told TypeScript that in the case of a `string`, we want to check for the existence of the `toUpperCase` member and in the case of a `number` we want to check for `toFixed`, the complier is happy.

But this kind of granular assertion is extremely verbose and cumbersome. Luckily, we can inform TypeScript once in our first `if` statement. And by doing so, TypeScript is intellignet enough to know that by the time we reach the `else if` clause, `id` must be a number. In order to do this, we need to create a function calleda type guard:

```typescript
function isString(val: string | number): val is string {
    return (<string>val).toUpperCase !== undefined;
}
```

Here, we've taken our `if` clause and put it in a function whose return value is a *type predicate*. Type predicates take the form: `parameterName is Type`.

Now, we can use `isString` in our code:

```typescript
// ...
if (isString(id)) {
    id = id.toUpperCase();
} else {
    id = id.toFixed();
}
```

Once we've checked `id`'s type using a type guard, TypeScript can be sure that in the `if` clause, `id` is a `string` and that in the `else` clause, it's a number. This will allow it to give you correct autocompletion in your editor and warn you if you try to use an incorrect method or property of `id` within the clause's block.

But what if we don't want to create a type guard function just to check a value's type? Fear not, there is a simpler way!

TypeScript recognizes the use of both `typeof` and `instanceof` as type guards. Allowing us to rewrite our code like so:

```typescript
// ...
if (typeof id === 'string') {
    id = id.toUpperCase();
} else if (typeof id === 'number') {
    id = id.toFixed();
}
```

The only acceptable string values that can be used in a `typeof` type guard are `"string"`, `"number"`, `"boolean"`, and `"symbol"`.

We can also use `instanceof` in case we're dealing with instances of a class and not primitive values:

```typescript
function getDate(): Date | number {
    return Math.random() > 0.5 ? new Date() : 17;
}

var dt = getDate();

if (dt instanceof Date) {
    console.log(dt.getFullYear());
} else {
    console.log(2000 + dt);
}
```

In this code, `getDate()` will give us either a `Date` object or a number representing the last two digits of the current year. If we try to add `2000` to a `Date` object, we get the following TypeScript error:

`Operator '+' cannot be applied to types '2000' and 'Date'.`

We need to figure out what type we're dealing with, and for that we use `instanceof`. Once we've narrowed down the value of `dt` to being an instance of `Date`, we can safely call `getFullYear()` on it, or add `2000` to the value in the the `else` clause.
