At first glance, union types don't seem very useful. If we have a variable of type `User | User[]`, there's not much we can do with it. We can't treat it like a single `User` because it might be a `User[]`. But we also can't treat it like a `User[]` because it might be a single `User`.
We get around this by handling both possibilities in our code. For example: if we're passed one user, we return their name. If we're passed an array of users, we return its length.
```ts
type User = {
name: string
};
function nameOrLength(userOrUsers: User | User[]) {
if (Array.isArray(userOrUsers)) {
// Inside this side of the if, userOrUsers' type is User[].
return userOrUsers.length;
} else {
// Inside this side of the if, userOrUsers' type is User.
return userOrUsers.name;
}
}
nameOrLength({name: 'Amir'}) //➞ 'Amir'
nameOrLength([{name: 'Amir'}, {name: 'Betty'}]) //➞ 2
```
`userOrUsers` is a `User | User[]`. Why are we allowed to access its `length` and its `name` here? Arrays don't have a `name`, and `User`s don't have a `length`.
```ts
const userOrUsers: User | User[] = [{name: 'Amir'}];
userOrUsers.name //➞ type error: Property 'name' does not exist on type 'User[]'
```
```ts
const userOrUsers: User | User[] = {name: 'Amir'};
userOrUsers.length //➞ type error: Property 'length' does not exist on type 'User'
```
The answer is that TypeScript can see our `if (Array.isArray(userOrUsers))` check. If `Array.isArray` is true, then the type can only be `User[]`, not `User`. The TypeScript compiler knows what `Array.isArray` means when used in a conditional.
The same logic applies to "else" side of the conditional. On that side, `Array.isArray(userOrUsers)` is false, so it must be a single `User`, not a `User[]`.
In both cases, we say that we've _narrowed_ the type. We've taken a wide type like `User | User[]` and reduced it to a narrower type like `User` or `User[]`.
The `Array.isArray` function is a _type guard_. When used inside an `if` or other conditional, a _type guard_ makes a guarantee about the type. It "guards" the code inside the conditional, ensuring that it only executes for certain types.