Mojtaba Pourkhanlar
About meProjectsBlog

  • 👤About me
  • 🧰Projects
  • ✍️Blog

TypeScript structure


خب TypeScript فقط «JavaScript با Type» نیست؛
بلکه یک Type System قدرتمند است که به ما کمک می‌کند:

  • زودتر خطاها را ببینیم
  • کد قابل‌اعتمادتر بنویسیم
  • و Refactor بدون ترس انجام دهیم
  • و در پروژه‌های بزرگ، sanity خودمان را حفظ کنیم

Type Annotation (تعیین نوع)

let price: number = 100;
let title: string = "Book";

Array Types

let numbers: number[]
 = [1, 2, 3]
;
// Or Generic:
let users: Array<string> = ["Ali", "Reza"]
;

Tuple

  • آرایه با طول و نوع ثابت:
  • ترتیب مقادیر مهم است.
let user: [number, string]
 = [1, "Ali"]
;

Any Type

  • اجازه استفاده از هر نوع داده:
  • در واقع TypeScript ،any را خاموش می‌کند
let data: any = 5;
data = "Hello";
data = true;

⚠️ توصیه: تا حد ممکن استفاده نشود.


Unknown Type

  • امن‌تر از any:
  • اما unknown شما را مجبور می‌کند Type Narrowing انجام دهید.
let value: unknown = "Hi";

if (typeof value === "string") {
  console.log(value.toUpperCase());
}

Void and Never

  • Void : برای توابع بدون خروجی
function log(msg: string): void {
  console.log(msg);
}
  • Never : برای توابعی که هرگز خاتمه نمی‌یابند
function error(msg: string): never {
  throw new Error(msg);
}

Union Types

  • پذیرش چند نوع
let id: number | string;

id = 10;
id = "ABC";

Intersection Types

  • ترکیب چند نوع
type A = { name: string };
type B = { age: number };

type C = A & B;

Type Alias

  • تعریف نوع سفارشی
type User = {
  id: number;
  name: string;
};

Interface

  • تعریف ساختار اشیاء
interface User {
  id: number;
  name: string;
}
// Extend
interface Admin extends User {
  role: string;
}

Optional و Readonly

// Optional
interface User {
  name: string;
  age?: number;
}
// Edit Form
--------------------------------
// ReadOnly
interface User {
  readonly id: number;
}
// Or
type ReadonlyUser = Readonly<User>;
// Not Change Data : جلوگیری از تغییر دیتا.

Function Types

function add(a: number, b: number): number {
  return a + b;
}
// Arrow Function
const sum = (a: number, b: number): number => a + b;

Type Assertion

  • تبدیل نوع
let input = document.getElementById("app") as HTMLElement;

Enum

خب Enum یعنی مجموعه‌ای از مقادیر ثابت با نام مشخص که در TypeScript خیلی استفاده میشه

enum Direction {
  Up,
  Down,
  Left,
  Right,
}

// استفاده
let move: Direction = Direction.Up;

// خروجی پشت صحنه JS
{
  Up: 0,
  Down: 1,
  Left: 2,
  Right: 3
}
// Enum با مقدار مشخص
enum Status {
  Success = 200,
  NotFound = 404,
  ServerError = 500
}
// Enum رشته‌ای
enum Role {
  Admin = "ADMIN",
  User = "USER"
}

Generics

خب Generics اجازه می‌دهد کدی بنویسیم که:

  • مستقل از نوع داده باشد
  • و Type-Safe باقی بماند
  • قابل استفاده مجدد باشد
async function fetcher<T>(url: string): Promise<T> {
  const res = await fetch(url);
  return res.json();
}

type User = { id: number; name: string };
const user = await fetcher<User>("/api/user");

// يه مثال كاربردى
function safeLocalStorage<T>(key: string, defaultValue: T) {
  return {
    get: (): T => {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : defaultValue;
    },
    set: (value: T) => {
      localStorage.setItem(key, JSON.stringify(value));
    },
  };
}

// استفاده
const userStorage = safeLocalStorage("user", { name: "", age: 0 });
userStorage.set({ name: "ali", age: 25 }); // فقط آبجکت با همین ساختار قبول میشه
const iser = userStorage.get(); // تایپ برگشتی هم دقیقا همون ساختار رو داره

Utility Types

// Partial
type UserPartial = Partial<User>;

// Required
type UserRequired = Required<User>;

// Pick
type UserName = Pick<User, "name">;

// Omit
type UserWithoutId = Omit<User, "id">;
Use Case واقعی Utility
Edit Form Partial
Validation Required
DTO / API Response Pick
Remove Sensitive Fields Omit
Config / Permission Record

keyof Operator

type UserKeys = keyof User;
// Export
"id" | "name";

typeof Operator

const person = {
  name: "Ali",
  age: 30,
};

type PersonType = typeof person;

Conditional Types

ميتونيم براساس شرط، تايپ هاى مختلف بسازيم. انعطاف پذيرى در تعريف تايپ يعنى همين.

type ApiResponse<T> = T extends "error"
  ? { status: 400; message: string }
  : { status: 200; data: any };

// استفاده
type ErrorResponse = ApiResponse<"error">; // status: 400
type SuccessResponse = ApiResponse<"success">; // status: 200

Template Literal Types

يكى از قابليت هاى جذاب تايپ اسكرييت كه خيليا نميشناسن. باهاش ميشه تايپ هاى يويا ساخت.

type Endpoint = `api/v1/${string}`;

// حالا فقط آدرس هاى معتبر قبول ميشن
const userEndpoint: Endpoint = "api/v1/users"; // درست
const wrongEndpoint: Endpoint = "v1/users"; // خطا

Type Guards

امنيت بيشتر در زمان اجرا. تايپ کاردها كمك ميكنن كدمون امن تر باشه:D

type User = { name: string; age: number };
type Admin = { name: string; permissions: string[]
 };

function isAdmin(user: User | Admin): user is Admin {
  return "permissions" in user;
}

// استفاده
function handleUser(user: User | Admin) {
  if (isAdmin(user)) {
    console.log(user.permissions); // حالا خطا نمیده
  }
}

Mapped Types

// Optional
type Optional<T> = {
  [K in keyof T]
?: T[K]
;
};

// Remove Readonly
type Mutable<T> = {
  -readonly [K in keyof T]
: T[K]
;
};

// Transform Property
type Booleanify<T> = {
  [K in keyof T]
: boolean;
};

Strict Mode

  • فعال‌سازی حالت سخت‌گیرانه در tsconfig.json
{
  "compilerOptions": {
    "strict": true
  }
}

مزایا:

  • کاهش باگ
  • بررسی Null
  • بررسی Type دقیق

Record Type

  • permission map ها

  • config object ها

  • mapping بین status → behavior

  • theme / variant / mode ها

  • وقتی کلیدها محدود و مشخص هستن

  • ساخت Object تایپ شده

type Roles = "admin" | "user";

const permissions: Record<Roles, string[]
> = {
  admin: ["read", "write"]
,
  user: ["read"]
,
};

ReturnType

// گرفتن خروجی تابع
function getUser() {
  return { id: 1, name: "Ali" };
}

type UserType = ReturnType<typeof getUser>;

Utility Type

خب Utility Type ها برای ساخت type های جدید از type های موجود استفاده می‌شن.

Partial :

  • همه پراپرتی ها آپشنال هستند
interface User {
  name: string;
  age: number;
}

type UpdateUser = Partial<User>;

// خروجی

{
 name?: string
 age?: number
}

Required :

  • همه پراپرتی ها اجباری هستند
type UserRequired = Required<User>;

Pick :

  • فقط بعضی property ها.
type UserName = Pick<User, "name">;

Omit :

  • حذف بعضی property ها.
type UserWithoutAge = Omit<User, "age">;

Record :

  • ساخت object type.
type UserRoles = Record<string, string>;

Readonly :

  • property ها immutable می‌شن.
type ReadonlyUser = Readonly<User>;