فصل اول: مقدمهای بر TypeScript
TypeScript یک سوپرست (superset) از JavaScript است که توسط مایکروسافت توسعه یافته است. این زبان برنامهنویسی متنباز (open-source) در سال ۲۰۱۲ معرفی شد و به سرعت به یکی از محبوبترین زبانها در توسعهی وب تبدیل شده است. TypeScript تمام ویژگیهای JavaScript را داراست، اما با افزودن قابلیت تایپ ایستا (static typing) و سایر امکانات پیشرفته، تجربه توسعه را به طور چشمگیری بهبود میبخشد.
چرا TypeScript؟
در پروژههای بزرگ JavaScript، مدیریت کد و کشف خطاها در زمان اجرا میتواند بسیار چالشبرانگیز باشد. TypeScript با ارائه سیستم نوع دهی قوی، این مشکلات را حل میکند:
- کشف خطاها در زمان کامپایل: بسیاری از خطاها قبل از اجرای کد شناسایی میشوند
- مستندسازی خودکار: تایپها به عنوان مستندات عمل میکنند
- پشتیبانی IDE پیشرفته: اتوکامپلیت (autocomplete) هوشمند، refactoring امن
- قابلیت نگهداری: کد تمیزتر و قابل درکتر
نصب و راهاندازی TypeScript
برای شروع کار با TypeScript، ابتدا باید Node.js را روی سیستم خود نصب کنید. سپس میتوانید TypeScript را به صورت گلوبال یا محلی نصب کنید:
# نصب گلوبال TypeScript
npm install -g typescript
# بررسی نسخه نصب شده
tsc --version
# ایجاد فایل پیکربندی tsconfig.json
tsc --init
# کامپایل فایل TypeScript به JavaScript
tsc index.ts
# اجرای TypeScript با watch mode
tsc --watch
پیکربندی tsconfig.json
فایل tsconfig.json قلب هر پروژه TypeScript است. این فایل تنظیمات کامپایلر را مشخص میکند:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
فصل دوم: انواع داده (Types) در TypeScript
سیستم نوعدهی TypeScript بسیار غنی و انعطافپذیر است. در این فصل به بررسی انواع اصلی میپردازیم:
انواع پایه (Primitive Types)
// رشته (String)
let username: string = "علی رضایی";
let message: string = `سلام ${username}!`;
// عدد (Number)
let age: number = 25;
let price: number = 99.99;
let binary: number = 0b1010;
let hex: number = 0xf00d;
// بولین (Boolean)
let isActive: boolean = true;
let hasPermission: boolean = false;
// تهی (Null) و تعریف نشده (Undefined)
let emptyValue: null = null;
let notDefined: undefined = undefined;
آرایهها (Arrays)
// روشهای تعریف آرایه
let numbers: number[] = [1, 2, 3, 4, 5];
let names: Array = ["علی", "رضا", "مریم"];
// آرایه چند بعدی
let matrix: number[][] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// Tuple (تاپل) - آرایه با طول و نوع ثابت
let person: [string, number, boolean] = ["علی", 25, true];
// Enum (شمارشی)
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
enum StatusCode {
Success = 200,
BadRequest = 400,
Unauthorized = 401,
NotFound = 404,
ServerError = 500
}
انواع خاص و پیشرفته
// Any - هر نوعی را میپذیرد
let variable: any = "میتواند هر چیزی باشد";
variable = 42;
variable = true;
// Unknown - شبیه any اما ایمنتر
let userInput: unknown;
userInput = "رشته";
userInput = 123;
// باید قبل از استفاده چک شود
if (typeof userInput === "string") {
console.log(userInput.toUpperCase());
}
// Void - برای توابعی که چیزی برنمیگردانند
function logMessage(message: string): void {
console.log(message);
}
// Never - برای توابعی که هرگز باز نمیگردند
function throwError(errorMsg: string): never {
throw new Error(errorMsg);
}
function infiniteLoop(): never {
while (true) {
// عملیات بینهایت
}
}
فصل سوم: اشیاء و اینترفیسها
مدلسازی دادههای پیچیده با استفاده از اشیاء و اینترفیسها:
// تعریف اینترفیس پایه
interface User {
id: number;
username: string;
email: string;
age?: number; // اختیاری
readonly createdAt: Date; // فقط خواندنی
}
// استفاده از اینترفیس
const user: User = {
id: 1,
username: "alirezaii",
email: "ali@example.com",
createdAt: new Date()
};
// اینترفیس با متدها
interface Calculator {
add(x: number, y: number): number;
subtract(x: number, y: number): number;
multiply(x: number, y: number): number;
divide(x: number, y: number): number;
}
// پیادهسازی اینترفیس
const calculator: Calculator = {
add: (x, y) => x + y,
subtract: (x, y) => x - y,
multiply: (x, y) => x * y,
divide: (x, y) => x / y
};
// اینترفیسهای قابل توسعه
interface Vehicle {
brand: string;
start(): void;
}
interface Car extends Vehicle {
doors: number;
drive(): void;
}
interface ElectricCar extends Car {
batteryCapacity: number;
charge(): void;
}
const tesla: ElectricCar = {
brand: "Tesla",
doors: 4,
batteryCapacity: 100,
start() {
console.log("ماشین روشن شد");
},
drive() {
console.log("در حال رانندگی");
},
charge() {
console.log("در حال شارژ");
}
};
فصل چهارم: کلاسها و برنامهنویسی شیءگرا
TypeScript از تمام ویژگیهای برنامهنویسی شیءگرا پشتیبانی کامل میکند:
// کلاس پایه
class Animal {
// ویژگیها
protected name: string;
private age: number;
public readonly species: string;
// سازنده (Constructor)
constructor(name: string, age: number, species: string) {
this.name = name;
this.age = age;
this.species = species;
}
// متدها
public makeSound(): void {
console.log("صدای حیوان");
}
public getInfo(): string {
return `${this.name} از گونه ${this.species} و ${this.age} سال سن دارد`;
}
// Getter و Setter
public get Age(): number {
return this.age;
}
public set Age(value: number) {
if (value > 0) {
this.age = value;
}
}
}
// ارثبری
class Dog extends Animal {
private breed: string;
constructor(name: string, age: number, breed: string) {
super(name, age, "سگ");
this.breed = breed;
}
// Override متد
public makeSound(): void {
console.log("واق واق!");
}
// متد جدید
public fetch(): void {
console.log(`${this.name} در حال آوردن توپ است`);
}
}
// کلاس انتزاعی (Abstract)
abstract class Shape {
constructor(public color: string) {}
abstract calculateArea(): number;
abstract calculatePerimeter(): number;
public getColor(): string {
return this.color;
}
}
class Circle extends Shape {
constructor(color: string, public radius: number) {
super(color);
}
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
calculatePerimeter(): number {
return 2 * Math.PI * this.radius;
}
}
class Rectangle extends Shape {
constructor(color: string, public width: number, public height: number) {
super(color);
}
calculateArea(): number {
return this.width * this.height;
}
calculatePerimeter(): number {
return 2 * (this.width + this.height);
}
}
// اینترفیسهای کلاس
interface Serializable {
serialize(): string;
}
interface Deserializable {
deserialize(data: string): void;
}
class UserProfile implements Serializable, Deserializable {
constructor(
public name: string,
public email: string,
private password: string
) {}
serialize(): string {
return JSON.stringify({
name: this.name,
email: this.email
});
}
deserialize(data: string): void {
const obj = JSON.parse(data);
this.name = obj.name;
this.email = obj.email;
}
}
فصل پنجم: Genericها (عمومیسازی)
Genericها یکی از قدرتمندترین ویژگیهای TypeScript هستند که به ما امکان میدهند کدهای قابل استفاده مجدد و نوعایمن بنویسیم:
// تابع Generic پایه
function identity(arg: T): T {
return arg;
}
const result1 = identity("Hello");
const result2 = identity(42);
const result3 = identity(true); // Type inference
// کلاس Generic
class Stack {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
isEmpty(): boolean {
return this.items.length === 0;
}
size(): number {
return this.items.length;
}
}
// استفاده از کلاس Generic
const numberStack = new Stack();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
const stringStack = new Stack();
stringStack.push("علی");
stringStack.push("رضا");
// Generic با محدودیت (Constraints)
interface HasLength {
length: number;
}
function logLength(arg: T): void {
console.log(`طول: ${arg.length}`);
}
logLength("رشته"); // 5
logLength([1, 2, 3]); // 3
logLength({ length: 10, name: "test" }); // 10
// Generic با چند پارامتر
function merge(obj1: U, obj2: V): U & V {
return { ...obj1, ...obj2 };
}
const merged = merge(
{ name: "علی", age: 25 },
{ city: "تهران", job: "توسعهدهنده" }
);
// Generic با مقادیر پیشفرض
function createArray(length: number, value: T): T[] {
return Array(length).fill(value);
}
const stringArray = createArray(5, "سلام");
const numberArray = createArray(5, 0);
فصل ششم: TypeScript با فریمورکهای مدرن
نحوه استفاده از TypeScript در فریمورکهای محبوب:
React با TypeScript
// تعریف پروپهای کامپوننت
interface UserProfileProps {
user: {
id: number;
name: string;
email: string;
age?: number;
};
onUpdate: (userData: Partial) => void;
isAdmin?: boolean;
}
const UserProfile: React.FC = ({
user,
onUpdate,
isAdmin = false
}) => {
const [isEditing, setIsEditing] = useState(false);
const handleUpdate = useCallback((data: Partial) => {
onUpdate(data);
}, [onUpdate]);
return (
{user.name}
ایمیل: {user.email}
{isAdmin && (
)}
);
};
// هوکهای Custom با TypeScript
function useLocalStorage(
key: string,
initialValue: T
): [T, (value: T) => void] {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
const setValue = (value: T) => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
Node.js با TypeScript
import express, { Request, Response, NextFunction } from "express";
import { ValidationError, NotFoundError } from "./errors";
// تعریف اینترفیسهای درخواست و پاسخ
interface AuthRequest extends Request {
user?: {
id: number;
email: string;
role: string;
};
}
interface PaginationQuery {
page?: number;
limit?: number;
sort?: string;
order?: "asc" | "desc";
}
// کنترلر TypeScript
class UserController {
async getUsers(
req: Request<{}, {}, {}, PaginationQuery>,
res: Response,
next: NextFunction
): Promise {
try {
const { page = 1, limit = 10, sort = "id", order = "asc" } = req.query;
const users = await UserService.getUsers({
page: Number(page),
limit: Number(limit),
sort,
order
});
res.json({
success: true,
data: users,
pagination: {
page: Number(page),
limit: Number(limit),
total: users.length
}
});
} catch (error) {
next(error);
}
}
}
فصل هفتم: بهترین روشها و الگوها
برای نوشتن کد TypeScript تمیز و قابل نگهداری:
۱. استفاده از Strict Mode
همیشه strict mode را فعال کنید تا از مزایای کامل TypeScript بهرهمند شوید.
۲. اجتناب از any
تا جای ممکن از any استفاده نکنید. به جای آن از unknown یا نوعدهی صحیح استفاده کنید.
۳. استفاده از Utility Types
// Partial - همه ویژگیها اختیاری
interface User {
id: number;
name: string;
email: string;
}
function updateUser(id: number, updates: Partial) {
// به روزرسانی کاربر
}
// Required - همه ویژگیها اجباری
type RequiredUser = Required;
// Readonly - همه ویژگیها فقط خواندنی
type ReadonlyUser = Readonly;
// Pick - انتخاب ویژگیهای خاص
type UserPreview = Pick;
// Omit - حذف ویژگیهای خاص
type UserWithoutId = Omit;
// Record - ایجاد آبجکت با کلیدها و مقدارهای مشخص
type UserRoles = Record;
// ReturnType - نوع مقدار بازگشتی تابع
type FetchUsersReturn = ReturnType;
// Parameters - نوع پارامترهای تابع
type FetchUsersParams = Parameters;
۴. سازماندهی کد
// ساختار پیشنهادی پروژه
src/
├── types/ # تعاریف نوع
│ ├── user.ts
│ ├── product.ts
│ └── index.ts
├── interfaces/ # اینترفیسها
├── enums/ # Enumها
├── models/ # مدلهای داده
├── services/ # سرویسهای کسبوکار
├── repositories/ # دسترسی به داده
├── controllers/ # کنترلرها
├── middleware/ # میدلورها
├── utils/ # توابع کمکی
├── config/ # تنظیمات
└── index.ts # نقطه ورود
نتیجهگیری
TypeScript نه تنها یک زبان برنامهنویسی، بلکه یک سرمایهگذاری بلندمدت در کیفیت کد و بهرهوری تیم است. با یادگیری و به کارگیری اصول صحیح TypeScript، میتوانید پروژههای بزرگتر، قابل اطمینانتر و قابل نگهداریتری بسازید.
یادگیری TypeScript ممکن است در ابتدا چالشبرانگیز باشد، اما مزایای آن در بلندمدت بسیار بیشتر از هزینههای یادگیری است. با تمرین مستمر و به کارگیری بهترین روشها، میتوانید به یک توسعهدهنده TypeScript ماهر تبدیل شوید.