> For the complete documentation index, see [llms.txt](https://book.pragmatic-objects.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.pragmatic-objects.com/practices/dont-check-types.md).

# Don't Check Types

## Metaphor

Imagine, you're entering a bar and a security guard stops you from doing so.&#x20;

They look at your face and scrutinise you up and down before refusing your entry for whatever reason popped in their head.

Isn't that rude ?

Is that acceptable ?

A somewhat better behavior would have been for the security guard to ask you for your ID, but that's still rude and uncomfortable. I don't like random people gazing at my ID.

Citizens in a well behaved society discuss and make an opinion through that discussion. They don't judge a book by its cover and they certainly don't ask to see the cover in the first place.

## Poor-lymorphism

The biggest problem about checking the type of an object is how it breaks the very idea and ideal of object ignorance.

As an object, I want to communicate to other objects through their public interface.

I don't care about who they are and how they do it. That's their problem and I don't want to have nothing to do with it. No, thanks !

I just want to know **they can understand my message** and **perform their part of the job.**

That's what polymorphism is about : **being able to communicate to a wealth of object with complete ignorance of who they are**.

Aren't we constantly[ told to reduce coupling](https://www.martinfowler.com/ieeeSoftware/coupling.pdf) ?

Message passing, polymorphism and event-driven systems are all about the lowest coupling ever ! [You really can't reduce it more](https://www.youtube.com/watch?v=w9a7eI6BlVc) without completely destroying it and separating the two systems !

That's a central concept of extensible systems and the heart of the [Open-Closed Principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle).

However, by checking the type of an object, **you're ruining everything.**

All our efforts, reduced to ashes.

Suddenly, our code becomes aware of concrete instances of classes. It looses its ability to treat classes with ignorance because its hanger got knowledge

**And everything you know can (and will) be held against you sooner or later**.

## Breaking the dependency

Let's take the example of multiple type of users : **BannedUser**, **RegularUser** and **AdminUser**. We'll assume a workflow where a user is trying to perform some sensible operation on data they own.

```typescript
if (user instanceof BannedUser) {
    throw new Error("You're not allowed to use this application");
} else if (user instanceof RegularUser) {
    if (!object.belongsTo(user)) {
        throw new Error("You're not authorized to perform this action")
    }
}

// AdminUser can do whatever they want
```

That's terrible design, because it somehow uses polymorphism (every class is a subclass of a common User class, or some User interface) but break-up at the first occasion. They'd make a terrible date.

Now what if we had this sort of code instead.

```typescript
if (!user.isBanned()) {
    throw new Error("You're not allowed to use this application");
} else if (!user.isAdmin() && !object.belongsTo(user)) {
    throw new Error("You're not authorized to perform this action")
}
```

That code is much better. At least, it doesn't rely on type checking !&#x20;

However, it's still bad code. Because every method is a reflection of its subtypes, which means not only subtypes know about their supertype, but the supertype also knows about its subtypes.&#x20;

```typescript
abstract class User {
    isBanned(): boolean;
    isAdmin(): boolean;
}

class BannedUser extends User {
    isBanned() { return true }
    isAdmin() { return false }
}

class AdminUser extends User {
    isBanned() { return false }
    isAdmin() { return true }
}
```

That's terrible. Adding a new type to the hierarchy will force us to add yet another method in the parent class. **The parent class knows to much**.

Now what if we had this sort of code instead.

```typescript
if (!user.canUseApp()) {
    throw new Error("You're not allowed to use this application");
} else if (!something.isManageableBy(user)) {
    throw new Error("You're not authorized to perform this action")
}
```

Not only are we decoupled from the classes, but by thinking in term of "capabilities", we're exhibiting composition !

```typescript
abstract class User {
    canUseApp(): boolean;
    isAllMighty(): boolean;
}

class BannedUser extends User {
    canUseApp() { return false }
    isAllMighty() { return false }
}

class AdminUser extends User {
    canUseApp() { return true }
    isAllMighty() { return true }
}
```

See how the semantic changes and how the return values are different ? These **falses** are a negative signal indicating a lack of possibility, which fits perfectly for a **`BannedUser`**. In the opposite, these **trues** are a positive signal.

You can rename `isAllMighty` by anything you like, as long as it reflects the capability of doing things that bypass regular checks.&#x20;

Actually, I believe you should.
