MohandOussadi
Back to Blog
TypeScript Best Practices

TypeScript Best Practices

April 20, 2024
3 min read
TypeScript
JavaScript
Best Practices

Introduction

JavaScript is the go-to language for the web, used both on the client side (browser) and the server side (with Node.js). But its flexibility comes with a drawback: it only catches certain errors at runtime, which can lead to bugs that are hard to anticipate, especially in complex projects.

To address these limitations, Microsoft created TypeScript. It’s a superset of JavaScript that adds static typing and compile-time error checking, while remaining 100% compatible with JavaScript. In other words, any valid JavaScript code is also valid TypeScript.

TypeScript’s main goal is simple: make development safer, clearer, and easier to maintain by catching errors before the program runs. It also improves collaboration by acting as implicit documentation through types.

Today, TypeScript is widely used in modern projects, whether for front-end applications (React, Vue, Angular) or back-end applications (Node.js, NestJS).

In this article, we’ll explore several best practices to get the most out of TypeScript in your projects.

Use explicit types

While TypeScript can infer types, declaring them explicitly improves code readability and reduces the risk of errors during refactoring.

function add(a: number, b: number): number {
  return a + b;
}

Prefer type over interface for simple objects

type is more flexible when combining or modifying structures using & (intersection) and | (union). Use interface mainly when working with classes or extensible object contracts.

Avoid the any type

The any type disables type checking and defeats the purpose of TypeScript. Use it only as a last resort, or prefer unknown for safer handling when the exact type is not yet known.

Enable strict mode

In your tsconfig.json, enable strict options like strict, noImplicitAny, and strictNullChecks. These settings will help catch more errors at compile time and improve overall code reliability.

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

Use built-in utility types

TypeScript provides handy utility types such as Partial<T>, Pick<T, K>, and Record<K, T>. These helpers let you manipulate and transform type structures without rewriting them from scratch.

Real-world example: TypeScript with React and Node.js

Let’s look at a simple example: a React form sending data to a Node.js API.

React side

type UserFormProps = {
  onSubmit: (data: { name: string; email: string }) => void;
};

function UserForm({ onSubmit }: UserFormProps) {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    onSubmit({ name, email }); // Error detected if a field is missing or mistyped
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <input value={email} onChange={(e) => setEmail(e.target.value)} />
      <button type="submit">Send</button>
    </form>
  );
}

Node.js side

import express, { Request, Response } from 'express';
const app = express();
app.use(express.json());

type User = {
  name: string;
  email: string;
};

app.post('/users', (req: Request<{}, {}, User>, res: Response) => {
  const { name, email } = req.body; // Error detected if a property is missing or has the wrong type
  res.json({ message: `User ${name} successfully added!` });
});

app.listen(3000, () => console.log('Server running on port 3000'));

In this example, static typing ensures that the data sent from React exactly matches what the Node.js server expects. If a field is missing or incorrectly typed, the error is caught at compile time—before the app even runs.

Conclusion

By adopting TypeScript and applying these best practices, you reduce the risk of bugs, improve code readability, and make long-term maintenance easier. Whether you work with React, Node.js, or any other JavaScript environment, TypeScript is a powerful ally for writing reliable and scalable applications.