TypeScript with React
Using TypeScript with React is a fantastic experience that catches many common bugs related to props and state.
Setup The easiest way to start a new project is with the official TypeScript template for Create React App:
Bash
npx create-react-app my-ts-app --template typescript
This sets up everything you need, including the .tsx file extension for components containing JSX.
Typing Function Components and Props You can type the props of a function component using an interface or type. The generic type React.FC (Function Component) is a common way to do this.
TypeScript
// src/components/Greeting.tsx
import React from 'react';
// 1. Define the shape of the props
interface GreetingProps {
  name: string;
  messageCount?: number;
}
// 2. Use the interface to type the component's props
const Greeting: React.FC<GreetingProps> = ({ name, messageCount = 0 }) => {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>You have {messageCount} new messages.</p>
    </div>
  );
};
export default Greeting;
Now, if you try to use this component without a name prop, TypeScript will give you a compile-time error!
Typing Hooks
- useState: TypeScript can often infer the type of state from its initial value. But for complex types or when the initial value is null, you should provide an explicit type.
- TypeScript
interface User { id: number; name: string; }
// Provide the type in angle brackets
const [user, setUser] = React.useState<User | null>(null);
- useRef: You need to type both the ref object and its .current property.
- TypeScript
const inputRef = React.useRef<HTMLInputElement>(null);
Typing Events React provides its own synthetic event types. You can import them to get full autocompletion on event handlers.
TypeScript
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  console.log(event.target.value);
};
return <input type="text" onChange={handleChange} />;
TypeScript with Node.js
TypeScript brings reliability and maintainability to back-end development with Node.js.
Setup For a Node.js project (e.g., using Express), you'll set it up manually.
- Initialize and install dependencies:
- Bash
npm init -y npm install express npm install --save-dev typescript ts-node nodemon @types/node @types/express
- ts-node: A tool that lets you run TypeScript files directly without a separate compile step, great for development.
- nodemon: A utility that automatically restarts your server when files change.
- Create tsconfig.json: npx tsc --init --rootDir src --outDir dist --module commonjs --esModuleInterop --strict
Writing a Type-Safe Express Server
TypeScript
// src/index.ts
import express, { Request, Response, NextFunction } from 'express';
const app = express();
const port = 3000;
app.get('/', (req: Request, res: Response) => {
  res.send('Hello from Type-Safe Express!');
});
interface User {
  id: string;
  name: string;
}
app.get('/api/users/:id', (req: Request<{ id: string }>, res: Response<User>) => {
  // TypeScript knows `req.params.id` is a string!
  console.log(req.params.id);
  // TypeScript will ensure the response body matches the 'User' interface.
  res.json({ id: req.params.id, name: 'Dummy User' });
});
app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});
By importing and using the Request and Response types from @types/express, you get type safety on your route handlers, including req.params, req.body, and the response object.
Running for Development You can use nodemon with ts-node to create a great development experience. Add a dev script to your package.json:
JSON
"scripts": {
  "dev": "nodemon src/index.ts"
}
Now run npm run dev to start your server, which will auto-reload on any change.