Keep Your Types And Interfaces Closer (In TypeScript)
Tags: web, javascript, typescript
Published: 2018-11-23 07:14:08

---
title: Keep Your Types And Interfaces Closer (In TypeScript)
published: true
description: TypeScript interfaces are powerful tools but they have to be used right; otherwise, your code becomes a bigger mess
tags: web, javascript, typescript
cover_image: https://antjanus.com/wp-content/uploads/2018/11/typescript-interfaces.jpg
---

I've been writing production TypeScript for a little over year and as a hobby for a couple of years longer than that. If you've never used TypeScript before, the quick way to describe it is that it's ES2015+ and types thrown together. Ie. modern JavaScript with real typing.

TypeScript is awesome and I love writing it and over time, I've noticed my own style and my own patterns emerge one of which I'd like to share and, hopefully, justify why I stick to those patterns.

## Local Interfaces > Global Interfaces

Interfaces in TypeScript are essentially object definitions that describe what an object should minimally look like. For example, if I had a `DatabaseConfig` interface, it might look something like this:

```typescript
interface DatabaseConfig {
  host: string,
  port: number,
  password: string
}

function connectToDb(dbConfig: DatabaseConfig) {
  // database connection config
}
```

What that basically means is that whenever you call the function `connectToDb`, you need to pass in an object that looks like the `DatabaseConfig` interface (along with the appropriate typings for its properties).

A pattern I picked up from a Golang styleguide article (I can't remember which) was the idea of "local interfaces", interfaces that describe exactly what I need from an object within that single file.

This `DatabaseConfig` interface, if shared, will grow exponentially to encompass the needs of every function that might touch this object. A `createDatabasePool` function might additionally look for a `poolSize` property on that config which will now be required by every function that references this interface, whether they use it or not. Imagine that we also had a function that would return a driver for that particular database so we might need a `type` property which no function cares about except the driver one.

Basically, sharing interfaces (or using what I call `global interfaces`) causes interfaces to bloat and to impose artificial requirements on properties that might not even be used by the function/code block/whatever that references the interface. It creates a strange "coupling" between possibly unrelated pieces of code.

Instead, what I suggest is writing interfaces local to a file which describe only the necessary properties required to be in the object by the code in that file. Eg. if you have a `createPool` function, you might write something like this:

```typescript
interface PoolConfig {
  poolSize: number
}

export function createPool(config: PoolConfig, driver) {
  // uses config.poolSize somewhere in the code
}
```

This way, we're telling the developer working in that file that all we really need is `poolSize` and we don't use anything else from that config object.

I've found this to be super useful in keeping with the idea that types are really just documentation that the computer can also view and utilize.

## Exceptions

There are a couple of exceptions to this rule.

Those exceptions are that if you're using object Models for your data, you might want to have those models available as interfaces as well to communicate to the developer (and the compiler) that you're really requiring this model. 

You might not care about the exact keys, you might care more about getting the actual Model (or something with the exact same shape).

The other exception to the rule is if you have complex objects that require keeping up with its complex shape. Imagine that you have an object that nests 5 levels deep. It's more prudent to have a single interface that you import which describes this rather than writing out, quite uselessly, complex nested interfaces.