TypeScript for React

Post Date:11 Feb 2026 - 09:55 PM
When building React applications, codebases often grow fast—components become more complex, props and state become harder to track, and small mistakes can create runtime bugs. That’s why I prefer TypeScript for React. TypeScript adds static typing, which helps me:

Catch errors during development (before runtime)
Make components easier to understand and refactor
Improve collaboration with better auto-completion and type hints
Write scalable, maintainable UI code

This blog is a practical TypeScript guide (with React-focused thinking), starting from setup to advanced types like generics and utility types.


Installation & Setup

Install TypeScript globally (optional)

npm install -g typescript

Create tsconfig.json

Inside your project:
tsc --init

TypeScript Auto Compiler (for Node/Backend)

If you're running a TypeScript server (like server.ts):
npm i -D ts-node-dev
Add a script in package.json:
{
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only server.ts"
}
}
Run:
npm run dev



Core TypeScript Types You Must Know

1) Primitive Types

number

let age: number = 25;
let price: number = 19.99;

string

let userName: string = "John Doe";

boolean

let isActive: boolean = true;

null and undefined

let data: null = null;
let value: undefined = undefined;

symbol

let sym: symbol = Symbol("key");

bigint

let bigNumber: bigint = 100n;



2) Literal Types

Literal types restrict values to exact options.
let direction: "north" | "south" | "east" | "west" = "north";
In React, this is helpful for variants like "primary" | "secondary".



3) Union Types (|)

Union means a variable can be one of multiple types.
let id: string | number = "123";
id = 123;
React use-case: API responses, optional inputs, polymorphic props.



4) Intersection Types (&)

Intersection combines multiple types into one.
type Person = { name: string };
type Employee = { employeeId: number };

let employee: Person & Employee = { name: "Alice", employeeId: 123 };



5) Optional Properties (?)

interface User {
name: string;
age?: number;
}

const user: User = { name: "Alice" };
React use-case: optional props.



6) Enum

Enums represent fixed values.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}

let move: Direction = Direction.Up;



Arrays, Tuples, and Objects

Array Types

let numbers: number[] = [1, 2, 3];
let names: string[] = ["Aminul", "Saimon"];
let moreNames: Array<string> = ["Alice", "Bob"];

Tuple

Tuples represent fixed-length arrays with fixed types.
let person: [string, number] = ["Alice", 30];



Type vs Interface (Most Common Confusion)

Type

type Point = {
x: number;
y: number;
};

const point: Point = { x: 10, y: 20 };

Interface

interface Point {
x: number;
y: number;
}

const point: Point = { x: 10, y: 20 };

Quick Rule I Follow

  • Use interface for React props, objects, and when you might extend later.
  • Use type for unions, intersections, utility combinations.



Function Typing

Normal Function

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

Arrow Function with Type Alias

type MathOperation = (a: number, b: number) => number;

const subtract: MathOperation = (x, y) => x - y;



Type Assertion (as)

When TypeScript can’t infer the type, you can assert it.
let someValue: unknown = "Hello, TypeScript!";
let strLength: number = (someValue as string).length;

console.log(strLength);
React use-case: ref, DOM casting, API unknown types.



Utility Types (Very Useful in React)

Partial<T> (makes all properties optional)

interface User {
name: string;
age: number;
}

const partialUser: Partial<User> = { name: "Alice" };
Use-case: update forms, patch requests.

Readonly<T>

const readOnlyUser: Readonly<User> = { name: "Alice", age: 30 };

Record<K, T>

const userRoles: Record<string, string> = {
alice: "admin",
bob: "user",
};

Pick<T, K>

type UserName = Pick<User, "name">;
const userName: UserName = { name: "Alice" };

Omit<T, K>

type UserWithoutAge = Omit<User, "age">;
const userWithoutAge: UserWithoutAge = { name: "Alice" };



Conditional Types

type IsString<T> = T extends string ? true : false;

type A = IsString<"hello">; // true
type B = IsString<123>; // false
This helps in advanced generic libraries and reusable React utilities.



Nullable Types

let name: string | null = "Alice";
name = null;



Readonly Properties

interface User {
readonly id: number;
name: string;
}

const user: User = { id: 1, name: "Alice" };
// user.id = 2; // Error



Generics (The Most Powerful Feature)

Generics let you write reusable and type-safe code that works for multiple data shapes.

Generic Array

const rollNumber2: Array<string> = ["12"];

type GenericArray<T> = Array<T>;
const roll: GenericArray<string> = ["aminul"];

Generic Object

interface Box<T> {
content: T;
}

const stringBox: Box<string> = { content: "Books" };
const numberBox: Box<number> = { content: 100 };

Generic Function

function identity<T>(value: T): T {
return value;
}

console.log(identity<string>("Hello"));
console.log(identity<number>(42));

Generic API Response (Real Project Example)

interface ApiResponse<T> {
status: number;
message: string;
data: T;
}

Example: User Response

interface User {
id: number;
name: string;
}

const userResponse: ApiResponse<User> = {
status: 200,
message: "User fetched successfully",
data: {
id: 1,
name: "Aminul",
},
};

Example: Product Response

interface Product {
id: number;
title: string;
price: number;
}

const productResponse: ApiResponse<Product> = {
status: 200,
message: "Product fetched successfully",
data: {
id: 10,
title: "Cricket Bat",
price: 120,
},
};



Complex Types (Nested + Array + Function)

Type Alias Example

type User = {
id: number;
name: string;
email?: string;
isActive: boolean;
address: {
street: string;
city: string;
zip: number;
};
getDetails: () => string;
};

const user: User = {
id: 2,
name: "John Doe",
isActive: false,
address: {
street: "456 Another St",
city: "Chittagong",
zip: 4000,
},
getDetails() {
return `${this.name} lives in ${this.address.city}`;
},
};

console.log(user.getDetails());



Spread vs Rest Operator (Very Common in React)

Spread Operator (...) — Expands Values

const team1: string[] = ["Aminul", "Sabbir", "Meskat"];
const team2: string[] = ["Saimon", "Tusar", "Alif"];

const allTeam = [...team1, ...team2];
console.log(allTeam);
React use-case: copying arrays/state immutably.

Rest Operator (...) — Collects Values

const greetFriends = (...friends: string[]) => {
friends.forEach((friend) => console.log(`Hi ${friend}`));
};

greetFriends("Abul", "Kabul", "Babul");
React use-case: flexible function params, component props spreading.

Cheat Sheet Type



Cheat Sheet for Interface