3 TypeScript Tricks You Can Use in JavaScript
Tags: javascript, typescript, codenewbie
Published: 2021-09-03 21:44:59

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi8vzugvaadx8g7a223w.png)

TypeScript is growing rapidly in popularity, but [isn't worth the effort for some projects](https://www.getrevue.co/profile/masteringjs/issues/is-typescript-worth-it-307679). However, even if you're writing JavaScript, there's some patterns you can learn from TypeScript. Here's 3 of our favorite TypeScript-inspired patterns for JavaScript.

## 1) [JavaScript Enums](https://masteringjs.io/tutorials/fundamentals/enum)

TypeScript has support for enums, which are a neat pattern for defining an object whose keys you can use in place of hard-coded strings.

```ts
enum Direction {
  Up,
  Down,
  Left,
  Right
}
```

JavaScript doesn't support enums. But TypeScript compiles to JavaScript, so what does the above code turn into? Turns out TypeScript enums compile into [JavaScript POJOs](https://masteringjs.io/tutorials/fundamentals/pojo).

```javascript
const Direction = {
  Up: 'Up',
  Down: 'Down',
  Left: 'Left',
  Right: 'Right'
};
```

You can also make `Direction` immutable using `Object.freeze()`, which makes `Direction` pretty close to a TypeScript enum. And that means you can do what you expect to do with enums in other languages:

* Get allowed enum values: `Object.keys(Direction)`
* Check if a value equals an enum value: `val === Direction.Up`
* Check if a value is in the enum: `Object.hasOwnProperty(val)`

## 2) [`orFail()`](http://thecodebarbarian.com/whats-new-in-mongoose-53-orfail-and-global-toobject.html) helpers to avoid null checks

TypeScript requires you to check for `null` query results in Mongoose. This is good practice, but also gets a bit cumbersome if you need to do it over and over again.

```ts
const doc = await Model.findOne();
// TypeScript reports an error "Object is possibly 'null'."
// Need to add a `if (doc != null)` check
doc._id;
```

Mongoose queries have a neat `orFail()` helper that throws an error if there's no result, which means you can go about using `doc` **without** explicitly checking for `null`. This is because `orFail()` marks the query as resolving to a [NonNullable](https://www.typescriptlang.org/docs/handbook/utility-types.html).

```ts
const doc = await Model.findOne().orFail();
// Works!
doc._id;
```

We use this `orFail()` pattern a lot in our TypeScript tests, because it saves us from having to add repetitive `if` checks. If the `orFail()` is triggered, the error bubbles up to error handling.

However, there's no reason why you can't use `orFail()` in JavaScript! Just because TypeScript isn't there to tell you there's a problem, doesn't mean the problem isn't there.

Similarly, if you have other functions that may return `null` if a value is not found, consider wrapping them in a function that throws an error if the value is not found. It can save you a lot of `null` checks!

## 3) Use [JavaScript maps](https://masteringjs.io/tutorials/fundamentals/map) for objects with unknown types

TypeScript makes it just a little easier to define a map with arbitrary keys than an object with arbitrary keys.

```ts
// An object with string keys and values of type `T`
interface AnyObject<T = any> { [k: string]: T }

// Map with string keys and values of type `T`
type AnyMap<T = any> = Map<string, T>;
```

TypeScript makes working with maps to store arbitrary key/value mappings easier, and with good reason: maps support mapping from keys of arbitrary type.

```javascript
const fakeMap = {};
fakeMap[1] = 'number';
fakeMap['1'] = 'string';
fakeMap; // { '1': string }

const map = new Map();
map.set(1, 'number');
map.set('1', 'string');
map; // Map(2) { 1 => 'number', '1' => 'string' }
```

The issue is that JavaScript object keys can only be strings or symbols, so JavaScript always converts object keys to strings. That's why you should use maps in cases where you aren't sure that the keys you're using are strings.