TypeScript Best Practices
Tags: typescript
Published: 2020-10-13 23:31:16

To make code easy to read and maintain, you should follow some best practices.

In this article, I am going to talk about some best practices you should follow to make everyone’s lives easier.

#Group Function Overloads Together

You can overload functions.

This means you can have multiple function signatures for a function, which TypeScript can check for.

To make your lives easier, you should group them together so that it’s easier to read:
```
function foo(a: string, b: string): string;

function foo(a: number, b: number): number;

function foo(a: any, b: any): any {
  console.log(a, b);
}
```

#Ordering Class Members

You may consider ordering class members to make the members easier to read.

You can order them by access modifiers, alphabetical order, etc.

It’s good to stick with one.

For example, instead of writing:
```
class Employee {
  private id: string;
  private empCode: number;
  private empName: string;
}
```

you write:
```
class Employee {
  private empCode: number;
  private empName: string;
  private id: string;
}
```
to sort them by alphabetical order.

#Don’t Use module Keyword for Namespaces

If you declare namespaces, then you should use the `namespace` keyword.

Instead of writing:
```
module Math {
  function add(a: number, b: number): number {
    return a + b;
  }
}
```

You write:
```
namespace Math {
  function add(a: number, b: number): number {
    return a + b;
  }
}
```

This way, you won’t confuse what you have with ES modules.

#Visibility Declarations for Class Members

To take advantage of the access control capabilities of TypeScript, you can add the visibility declarations or class members.

For example, you write:
```
class Employee {
  private getSalary(): number {
    return 90000;
  }
}
```

You added the `private` access modifier so that `getSalary` can only be called by other methods in the class.

There’s also the `public` modifier to make the member available to outside code.

`protected` makes the member available to subclasses and the current class.

`public` is the default.

You can also do the same for instance variables:
```
class Employee {
  private empCode: number;
}
```

#Eliminate the Use of any Types

You can eliminate the use of `any` types in your code to take advantage of TypeScript’s type-checking capabilities.

If you need something more flexible than static types, there are many ways to define them.

You can use literal types to restrict values to only some literals.

There’re union types to let you check for members for multiple types.

The intersection type makes sure that the variable has members that are in both types.

Index signatures let you check for dynamic properties.

There’re many ways to avoid `any`.

For example, instead of writing:
```
let bar: any;
```
you write:
```
let foo: string;
```

#No Empty Interface

You shouldn’t have empty interfaces in your code since they’re useless.

So instead of writing:
```
interface I {}
```
You write:
```
interface I {
  bar: number;
}
```

#No for-in Loops

for-in loops are legacy JavaScript syntax which has better modern alternatives.

It’s bad since you need to use the `hasOwnProperty` to check for non-inherited properties with it.

Better alternatives include `Object.keys` to get the non-inherited keys of an object.

`Object.values` to get the values and `Object.entries` to get all entries.

So instead of writing:
```
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(obj[key]);
  }
}
```
you write:
```
for (const key in Oject.keys(obj)) {
  console.log(obj[key]);
}
```

#No Import Side Effects

`import` should be used for import module members and using them.

If they perform side effects, then it’s not good because it’s hard to statically analyze the code.

So instead of writing:
```
import 'foo';
```
you write:
```
import { bar } from 'foo';
```

Some exceptions may be importing CSS with Webpack as modules.
So you may still write:
```
import 'styles.css';
```

#No Explicit Type Declarations for Variable or Parameters with Literal Values

It’s redundant to have type declarations for variables or parameters that are assigned with numbers strings or boolean.

TypeScript can check these without an explicit type.

Therefore, instead of writing:
```
const foo: number = 10;
```
You write:
```
const foo = 10;
```

#Conclusion

Grouping things together make them easier to read.

Visibility modifiers are a useful TypeScript feature.

`any` types can be replaced with many things.

Use `namespace` to declare namespace code.

That’s it for today!

Thanks for your reading and stay tuned!