React TypeScript
TypeScript vs JavaScript
Here are the key differences between TypeScript and JavaScript:
| Feature | TypeScript | JavaScript |
|---|---|---|
| Type System | Static typing with type annotations | Dynamic typing |
| Error Detection | Compile-time errors | Runtime errors |
| Code Example | let name: string = "John"; |
let name = "John"; |
| Object Properties | Must match defined interface | Can add any properties |
| IDE Support | Better autocomplete and hints | Basic autocomplete |
Examples for Each Feature
1. Type System
TypeScript:
// Types are explicitly declared
let name: string = "John";
let age: number = 25;
let active: boolean = true;
let numbers: number[] = [1, 2, 3];
// Type error caught at compile time
age = "25"; // Error: Type 'string' is not
// assignable to type 'number'
JavaScript:
// Types are inferred dynamically
let name = "John";
let age = 25;
let active = true;
let numbers = [1, 2, 3];
// No type checking
age = "25"; // Works, but might cause issues
// later in the code
2. Error Detection
TypeScript:
interface User {
name: string;
email: string;
}
function sendEmail(user: User) {
console.log(user.email);
}
// Error caught during compilation
sendEmail({ name: "John" }); // Error: missing
// email property
JavaScript:
function sendEmail(user) {
console.log(user.email);
}
// Error only appears when running
sendEmail({ name: "John" });
// Runtime error: Cannot read property
// 'email' of undefined
3. Object Properties
TypeScript:
interface Person {
name: string;
age: number;
}
const person: Person = {
name: "John",
age: 25
};
// Error: Property 'location' does not
// exist on type 'Person'
person.location = "NYC";
JavaScript:
const person = {
name: "John",
age: 25
};
// Can freely add new properties
person.location = "NYC"; // Works fine
// But might cause issues if property
// name is misspelled or used
// inconsistently
4. IDE Support
TypeScript:
interface User {
name: string;
email: string;
sendMessage(msg: string): void;
}
const user: User = {
name: "John",
email: "john@example.com",
sendMessage(msg) {
console.log(msg);
}
};
// IDE shows all available properties
user. // Shows: name, email, sendMessage
JavaScript:
const user = {
name: "John",
email: "john@example.com",
sendMessage(msg) {
console.log(msg);
}
};
// IDE might not show all properties
// or might show incorrect ones
user. // Limited autocomplete
// support
5. Function Parameters
TypeScript:
function greet(name: string, age: number) {
return `${name} is ${age} years old`;
}
greet("John", 25); // OK
greet("John", "25"); // Error!
JavaScript:
function greet(name, age) {
return `${name} is ${age} years old`;
}
greet("John", 25); // OK
greet("John", "25"); // Also OK
What is TypeScript in React?
TypeScript adds static typing to JavaScript, making your React code more reliable and easier to maintain.
Benefits of using TypeScript with React:
- Catch errors early during development
- Better code completion in your editor
- Easier refactoring
- Clear interface definitions for components
Creating a React TypeScript Project
Create a new React project with TypeScript:
Using Vite (Recommended)
npm create vite@latest my-react-ts -- --template react-ts
Basic Component Example
Here's a simple React component with TypeScript:
Example
interface GreetingProps {
name: string;
age?: number; // Optional prop
}
function Greeting({ name, age }: GreetingProps) {
return (
<div>
<h1>Hello, {name}!</h1>
{age && <p>You are {age} years old</p>}
</div>
);
}
function App() {
return (
<div>
<Greeting name="John" age={25} />
<Greeting name="Jane" />
</div>
);
}
Typing Hooks
How to use TypeScript with React hooks:
Example
import { useState, useEffect } from 'react';
interface User {
id: number;
name: string;
email: string;
}
function UserProfile() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch('/api/user')
.then(res => res.json())
.then((data: User) => setUser(data))
.finally(() => setLoading(false));
}, []);
if (loading) return <div>Loading...</div>;
if (!user) return <div>No user found</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
Event Handling
TypeScript helps you handle events correctly:
Example
function Form() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Form handling logic
};
const handleChange = (e: React.ChangeEvent) => {
console.log(e.target.value);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
onChange={handleChange}
placeholder="Type here..."
/>
<button type="submit">Submit</button>
</form>
);
}
Common Types
Frequently used TypeScript types in React:
// Props with children
interface ContainerProps {
children: React.ReactNode;
className?: string;
}
// Event handlers
type ButtonProps = {
onClick: (e: React.MouseEvent) => void;
disabled?: boolean;
}
// Style objects
interface Styles {
color: string;
backgroundColor?: string;
[key: string]: string | undefined;
}
// Ref types
const inputRef = useRef<HTMLInputElement>(null);
Note: TypeScript's type inference is quite good. You don't always need to explicitly declare types when they can be inferred.
Best Practices
- Use interfaces for objects that represent a clear concept
- Use type for unions, intersections, or mapped types
- Make props optional when they have sensible defaults
- Use the built-in React types when possible
- Keep type definitions close to where they're used