Cheatsheet: JavaScript, TypeScript and React¶
Quick reference for the most commonly used syntax and patterns. This is not a substitute for the modules — use it for revision and as a desk reference.
JavaScript Array Methods¶
const nums = [1, 2, 3, 4, 5];
// map — transform each element, return new array
const doubled = nums.map(n => n * 2); // [2, 4, 6, 8, 10]
// filter — keep elements where predicate is true
const evens = nums.filter(n => n % 2 === 0); // [2, 4]
// reduce — fold array to a single value
const sum = nums.reduce((acc, n) => acc + n, 0); // 15
// find — first element matching predicate (or undefined)
const first = nums.find(n => n > 3); // 4
// findIndex — index of first match (or -1)
const idx = nums.findIndex(n => n > 3); // 3
// some — true if any element matches
const hasEven = nums.some(n => n % 2 === 0); // true
// every — true if all elements match
const allPos = nums.every(n => n > 0); // true
// flat — flatten nested arrays
const nested = [[1, 2], [3, 4]];
const flat = nested.flat(); // [1, 2, 3, 4]
// flatMap — map then flatten one level
const words = ['hello world', 'foo bar'];
const letters = words.flatMap(s => s.split(' ')); // ['hello', 'world', 'foo', 'bar']
// includes — check membership
nums.includes(3); // true
// slice — extract subarray (non-mutating)
nums.slice(1, 3); // [2, 3]
// spread to copy or combine
const copy = [...nums];
const combined = [...nums, 6, 7];
Async Patterns¶
// Promises
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
// async/await (preferred)
async function loadData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
return data;
} catch (err) {
console.error('Failed:', err);
throw err; // re-throw so caller knows it failed
}
}
// Promise.all — run multiple async operations in parallel
async function loadAll() {
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
]);
return { users, posts };
}
// Promise.allSettled — like Promise.all but doesn't short-circuit on failure
const results = await Promise.allSettled([
fetch('/api/a').then(r => r.json()),
fetch('/api/b').then(r => r.json()),
]);
// results[0] = { status: 'fulfilled', value: ... }
// results[1] = { status: 'rejected', reason: ... }
TypeScript Type Syntax¶
// Primitive types
let name: string = 'Alice';
let age: number = 30;
let active: boolean = true;
let nothing: null = null;
let missing: undefined = undefined;
// Union types
let id: string | number = 'abc';
id = 123; // also valid
// Literal types
type Direction = 'north' | 'south' | 'east' | 'west';
type StatusCode = 200 | 400 | 401 | 404 | 500;
// Arrays
let scores: number[] = [90, 85, 77];
let tags: Array<string> = ['js', 'ts']; // equivalent
// Tuples
let point: [number, number] = [10, 20];
// Object types with interface
interface User {
id: number;
name: string;
email?: string; // optional
readonly createdAt: Date; // readonly
}
// Type alias (can express anything interface can, plus unions/intersections)
type ID = string | number;
type Point = { x: number; y: number };
// Generics
function identity<T>(value: T): T {
return value;
}
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
// Utility types
type PartialUser = Partial<User>; // all fields optional
type RequiredUser = Required<User>; // all fields required
type ReadonlyUser = Readonly<User>; // all fields readonly
type UserName = Pick<User, 'id' | 'name'>; // only id and name
type WithoutEmail = Omit<User, 'email'>; // everything except email
type UserOrNull = User | null;
type NonNullUser = NonNullable<UserOrNull>; // removes null/undefined
// Type narrowing
function printId(id: string | number) {
if (typeof id === 'string') {
console.log(id.toUpperCase()); // TypeScript knows id is string here
} else {
console.log(id.toFixed(2)); // TypeScript knows id is number here
}
}
React Hooks API¶
import { useState, useEffect, useContext, useReducer,
useMemo, useCallback, useRef } from 'react';
// useState — local component state
const [count, setCount] = useState<number>(0);
setCount(count + 1); // direct value
setCount(prev => prev + 1); // functional update (safe with stale closures)
// useEffect — side effects and subscriptions
useEffect(() => {
document.title = `Count: ${count}`;
return () => { /* cleanup runs before next effect or unmount */ };
}, [count]); // dependency array — effect runs when count changes
useEffect(() => { /* runs once on mount */ }, []);
useEffect(() => { /* runs on every render */ }); // no array — usually a mistake
// useRef — mutable ref, does not trigger re-render
const inputRef = useRef<HTMLInputElement>(null);
inputRef.current?.focus();
// Storing a mutable value (not for rendering)
const prevCountRef = useRef<number>(0);
// useMemo — memoize expensive computation
const expensiveValue = useMemo(() => compute(a, b), [a, b]);
// useCallback — memoize function reference (for stable props/deps)
const handleClick = useCallback(() => setCount(c => c + 1), []);
// useReducer — complex state logic
type Action = { type: 'increment' } | { type: 'reset' };
function reducer(state: number, action: Action): number {
switch (action.type) {
case 'increment': return state + 1;
case 'reset': return 0;
}
}
const [state, dispatch] = useReducer(reducer, 0);
dispatch({ type: 'increment' });
// useContext — consume context without prop drilling
const theme = useContext(ThemeContext); // ThemeContext created with createContext()
Common React Patterns¶
// Function component with typed props
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
variant?: 'primary' | 'secondary';
}
function Button({ label, onClick, disabled = false, variant = 'primary' }: ButtonProps) {
return (
<button
onClick={onClick}
disabled={disabled}
className={`btn btn-${variant}`}
>
{label}
</button>
);
}
// Custom hook pattern
function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setStoredValue = (newValue: T) => {
setValue(newValue);
window.localStorage.setItem(key, JSON.stringify(newValue));
};
return [value, setStoredValue] as const;
}
// Conditional rendering
function Status({ isLoading, error, data }: StatusProps) {
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
if (!data) return null;
return <div>{data.name}</div>;
}
// List rendering — always provide a stable key
function List({ items }: { items: Item[] }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
// Context pattern
const ThemeContext = createContext<'light' | 'dark'>('light');
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
return (
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>
);
}