الفئات في TypeScript — دليل شامل Classes 2026
دليل عملي مفصل للفئات في TypeScript — التعريف، الوراثة، Access Modifiers، Abstract Classes، مع تمارين وحلول
في المقال السابق، تعلمت الدوال مع الأنواع. الآن سنتعمق في الفئات (Classes) — وهي أساس البرمجة كائنية التوجه (OOP) في TypeScript.
في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم الفئات، والوراثة، ومحددات الوصول، مع تمارين وحلول.
ما هي الفئة (Class)؟
الفئة هي قالب لإنشاء كائنات (Objects). تحتوي على:
- الخصائص (Properties): البيانات.
- الطرق (Methods): الدوال.
- Constructor: دالة تُنفَّذ عند إنشاء الكائن.
مثال بسيط:
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): string {
return `مرحباً، اسمي ${this.name} وعمري ${this.age}`;
}
}
const ahmed = new Person("أحمد", 25);
console.log(ahmed.greet()); // مرحباً، اسمي أحمد وعمري 25
شرح:
class Person: تعريف فئة.name: string: خاصية.constructor: دالة تُنفَّذ عندnew Person(...).greet(): طريقة (method).new Person("أحمد", 25): إنشاء كائن جديد.
لماذا نحتاج الفئات؟
- التنظيم: تجميع البيانات والوظائف معاً.
- إعادة الاستخدام: الوراثة (Inheritance).
- الأمان: تحديد من يمكنه الوصول للبيانات.
- الوضوح: الكود يعكس كائنات العالم الحقيقي.
تعريف فئة بسيطة
class Car {
brand: string;
model: string;
year: number;
constructor(brand: string, model: string, year: number) {
this.brand = brand;
this.model = model;
this.year = year;
}
getInfo(): string {
return `${this.brand} ${this.model} (${this.year})`;
}
}
const car = new Car("تويوتا", "كامري", 2024);
console.log(car.getInfo()); // تويوتا كامري (2024)
Constructor — البانية
الـ Constructor هي دالة خاصة تُنفَّذ عند إنشاء الكائن:
class User {
name: string;
email: string;
constructor(name: string, email: string) {
this.name = name;
this.email = email;
console.log("تم إنشاء مستخدم جديد!");
}
}
const user = new User("أحمد", "[email protected]");
// يطبع: تم إنشاء مستخدم جديد!
طريقة مختصرة (Parameter Properties)
يمكنك تعريف الخصائص مباشرة في الـ Constructor:
class Person {
constructor(
public name: string,
public age: number,
private email: string
) {}
getInfo(): string {
return `${this.name} (${this.age})`;
}
}
const person = new Person("أحمد", 25, "[email protected]");
console.log(person.name); // أحمد
console.log(person.age); // 25
// console.log(person.email); // ❌ خطأ: private
الفائدة: كود أقل، ووضوح أكثر.
محددات الوصول (Access Modifiers)
TypeScript توفر 3 محددات وصول:
| المحدد | الوصول | الاستخدام |
|---|---|---|
public | من أي مكان (افتراضي) | للخصائص العامة |
private | داخل الفئة فقط | للبيانات الحساسة |
protected | داخل الفئة والفئات الوريثة | للمشاركة مع الفئات الفرعية |
1. public
class Person {
public name: string;
constructor(name: string) {
this.name = name;
}
}
const person = new Person("أحمد");
console.log(person.name); // ✅ أحمد
2. private
class BankAccount {
private balance: number;
constructor(initialBalance: number) {
this.balance = initialBalance;
}
deposit(amount: number): void {
this.balance += amount;
}
getBalance(): number {
return this.balance;
}
}
const account = new BankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 1500
// console.log(account.balance); // ❌ خطأ: private
3. protected
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
bark(): void {
console.log(`${this.name} يقول: هاو هاو!`); // ✅ يمكن الوصول
}
}
const dog = new Dog("روكي");
dog.bark(); // روكي يقول: هاو هاو!
Readonly Properties
class User {
readonly id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
const user = new User(1, "أحمد");
user.name = "محمد"; // ✅
// user.id = 2; // ❌ خطأ: readonly
الوراثة (Inheritance)
الوراثة تسمح لفئة بأخذ خصائص وطرق فئة أخرى:
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log("صوت غير معروف");
}
}
class Dog extends Animal {
makeSound(): void {
console.log(`${this.name} يقول: هاو هاو!`);
}
}
class Cat extends Animal {
makeSound(): void {
console.log(`${this.name} يقول: مياو!`);
}
}
const dog = new Dog("روكي");
dog.makeSound(); // روكي يقول: هاو هاو!
const cat = new Cat("مشمش");
cat.makeSound(); // مشمش يقول: مياو!
شرح:
extends Animal: فئةDogترث منAnimal.makeSound(): إعادة تعريف (override) للطريقة.
super — استدعاء الفئة الأم
class Animal {
constructor(public name: string) {}
makeSound(): void {
console.log("صوت غير معروف");
}
}
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name); // استدعاء constructor الفئة الأم
}
makeSound(): void {
super.makeSound(); // استدعاء طريقة الفئة الأم
console.log("هاو هاو!");
}
}
const dog = new Dog("روكي", "جولدن");
dog.makeSound();
// صوت غير معروف
// هاو هاو!
الفئات المجردة (Abstract Classes)
الفئة المجردة لا يمكن إنشاء كائن منها مباشرة، بل يجب أن تُورَّث:
abstract class Shape {
abstract area(): number; // يجب على الفئة الوريثة تنفيذها
describe(): string {
return `المساحة: ${this.area()}`;
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super();
}
area(): number {
return this.width * this.height;
}
}
const circle = new Circle(5);
console.log(circle.describe()); // المساحة: 78.5398...
const rect = new Rectangle(4, 6);
console.log(rect.describe()); // المساحة: 24
// const shape = new Shape(); // ❌ خطأ: abstract
Getters و Setters
class User {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
if (value.length < 2) {
throw new Error("الاسم قصير جداً");
}
this._name = value;
}
}
const user = new User();
user.name = "أحمد";
console.log(user.name); // أحمد
// user.name = "أ"; // ❌ خطأ: الاسم قصير جداً
Static Properties و Methods
Static تعني أن الخاصية أو الطريقة تنتمي للفئة نفسها، وليس للكائنات:
class MathUtils {
static PI: number = 3.14159;
static add(a: number, b: number): number {
return a + b;
}
static multiply(a: number, b: number): number {
return a * b;
}
}
console.log(MathUtils.PI); // 3.14159
console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.multiply(4, 5)); // 20
// لا تحتاج إلى new MathUtils()
تنفيذ الواجهات (implements)
الفئات يمكنها تنفيذ الواجهات:
interface Animal {
name: string;
makeSound(): void;
}
class Dog implements Animal {
constructor(public name: string) {}
makeSound(): void {
console.log(`${this.name} يقول: هاو هاو!`);
}
}
const dog = new Dog("روكي");
dog.makeSound();
مثال عملي: نظام موظفين
abstract class Employee {
constructor(
public id: number,
public name: string,
protected salary: number
) {}
abstract calculateBonus(): number;
getDetails(): string {
return `الموظف: ${this.name} (ID: ${this.id})`;
}
getSalary(): number {
return this.salary;
}
}
class Manager extends Employee {
constructor(id: number, name: string, salary: number, private teamSize: number) {
super(id, name, salary);
}
calculateBonus(): number {
return this.salary * 0.2; // 20% مدير
}
}
class Developer extends Employee {
constructor(id: number, name: string, salary: number, private language: string) {
super(id, name, salary);
}
calculateBonus(): number {
return this.salary * 0.1; // 10% مطور
}
getLanguage(): string {
return this.language;
}
}
const manager = new Manager(1, "أحمد", 10000, 5);
console.log(manager.getDetails()); // الموظف: أحمد (ID: 1)
console.log(manager.calculateBonus()); // 2000
const developer = new Developer(2, "محمد", 8000, "TypeScript");
console.log(developer.getDetails()); // الموظف: محمد (ID: 2)
console.log(developer.calculateBonus()); // 800
console.log(developer.getLanguage()); // TypeScript
تمارين عملية
تمرين 1: فئة Person
أنشئ فئة Person لها name و age وطريقة greet().
الحل:
class Person {
constructor(public name: string, public age: number) {}
greet(): string {
return `مرحباً، اسمي ${this.name} وعمري ${this.age}`;
}
}
const person = new Person("أحمد", 25);
console.log(person.greet());
تمرين 2: فئة Rectangle
أنشئ فئة Rectangle لها width و height، وطريقة area().
الحل:
class Rectangle {
constructor(public width: number, public height: number) {}
area(): number {
return this.width * this.height;
}
}
const rect = new Rectangle(5, 10);
console.log(rect.area()); // 50
تمرين 3: الوراثة
أنشئ فئة Animal، ثم Dog و Cat ترث منها.
الحل:
class Animal {
constructor(public name: string) {}
makeSound(): void {
console.log("صوت غير معروف");
}
}
class Dog extends Animal {
makeSound(): void {
console.log(`${this.name}: هاو هاو!`);
}
}
class Cat extends Animal {
makeSound(): void {
console.log(`${this.name}: مياو!`);
}
}
new Dog("روكي").makeSound(); // روكي: هاو هاو!
new Cat("مشمش").makeSound(); // مشمش: مياو!
تمرين 4: Private
أنشئ فئة BankAccount لها balance خاص.
الحل:
class BankAccount {
private balance: number = 0;
deposit(amount: number): void {
if (amount > 0) this.balance += amount;
}
withdraw(amount: number): void {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
}
}
getBalance(): number {
return this.balance;
}
}
const account = new BankAccount();
account.deposit(1000);
account.withdraw(300);
console.log(account.getBalance()); // 700
تمرين 5: Abstract Class
أنشئ فئة مجردة Shape لها area().
الحل:
abstract class Shape {
abstract area(): number;
describe(): string {
return `المساحة: ${this.area()}`;
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
}
console.log(new Circle(5).describe());
تمرين 6: Static
أنشئ فئة MathUtils لها دوال static.
الحل:
class MathUtils {
static add(a: number, b: number): number {
return a + b;
}
static subtract(a: number, b: number): number {
return a - b;
}
}
console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.subtract(5, 3)); // 2
تمرين 7: Getters و Setters
أنشئ فئة Temperature لها celsius مع getter/setter.
الحل:
class Temperature {
private _celsius: number = 0;
get celsius(): number {
return this._celsius;
}
set celsius(value: number) {
if (value < -273.15) {
throw new Error("أقل من الصفر المطلق!");
}
this._celsius = value;
}
get fahrenheit(): number {
return this._celsius * 9 / 5 + 32;
}
}
const temp = new Temperature();
temp.celsius = 25;
console.log(temp.celsius); // 25
console.log(temp.fahrenheit); // 77
تمرين 8: نظام حيوانات
أنشئ نظاماً كاملاً بفئات حيوانات.
الحل:
abstract class Animal {
constructor(public name: string) {}
abstract makeSound(): string;
}
class Dog extends Animal {
makeSound(): string {
return `${this.name}: هاو هاو!`;
}
}
class Cat extends Animal {
makeSound(): string {
return `${this.name}: مياو!`;
}
}
class Cow extends Animal {
makeSound(): string {
return `${this.name}: مووو!`;
}
}
const animals: Animal[] = [
new Dog("روكي"),
new Cat("مشمش"),
new Cow("بقرودة"),
];
animals.forEach((animal) => console.log(animal.makeSound()));
حل المشاكل الشائعة
🔴 المشكلة 1: Property 'X' has no initializer
السبب: خاصية لم تُهيأ في الـ Constructor.
class Person {
name: string; // ❌ خطأ
}
الحل:
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
}
// أو:
class Person {
name: string = "";
}
// أو:
class Person {
constructor(public name: string) {}
}
🔴 المشكلة 2: Cannot access 'X' before initialization
السبب: استخدام this قبل super().
class Dog extends Animal {
constructor(name: string) {
this.name = name; // ❌
super();
}
}
الحل: استدعِ super() أولاً:
class Dog extends Animal {
constructor(name: string) {
super();
this.name = name; // ✅
}
}
🔴 المشكلة 3: Cannot create an instance of an abstract class
السبب: محاولة إنشاء كائن من فئة مجردة.
abstract class Shape {}
const shape = new Shape(); // ❌
الحل: أنشئ فئة فرعية ترث منها.
🔴 المشكلة 4: Property 'X' is private
السبب: الوصول لخاصية private من خارج الفئة.
class User {
private password: string = "123";
}
const user = new User();
console.log(user.password); // ❌
الحل: اجعلها public أو أضف getter.
جدول الأوامر الأساسية
| الأمر | الوظيفة |
|---|---|
class X { } | تعريف فئة |
constructor() { } | الـ Constructor |
new X() | إنشاء كائن |
class X extends Y | وراثة |
super() | استدعاء الفئة الأم |
public, private, protected | محددات الوصول |
readonly | للقراءة فقط |
abstract | فئة مجردة |
static | ينتمي للفئة |
get / set | Getters/Setters |
implements | تنفيذ واجهة |
قائمة تحقق نهائية
| المهمة | الحالة |
|---|---|
| فهم تعريف الفئات والـ Constructor | ⬜ |
| محددات الوصول (public, private, protected) | ⬜ |
| الوراثة (extends) و super | ⬜ |
| الفئات المجردة (abstract) | ⬜ |
| Static Properties/Methods | ⬜ |
| Getters و Setters | ⬜ |
| تنفيذ الواجهات (implements) | ⬜ |
| حل التمارين الثمانية | ⬜ |
ماذا بعد هذا المقال؟
الآن بعد أن أتقنت الفئات، أنت جاهز للمقال التالي:
- الأدوية (Generics) — الأنواع العامة.
- الأنواع المتقدمة — Utility Types.
- مشروع React — تطبيق عملي.
الخلاصة
في هذا المقال، تعلمت:
- ✅ تعريف الفئات والـ Constructor.
- ✅ محددات الوصول (public, private, protected).
- ✅ Readonly Properties.
- ✅ الوراثة (extends) و super.
- ✅ الفئات المجردة (abstract).
- ✅ Getters و Setters.
- ✅ Static Properties/Methods.
- ✅ تنفيذ الواجهات (implements).
تذكر: الفئات هي أساس البرمجة كائنية التوجه. أتقنها جيداً، وستتمكن من بناء تطبيقات معقدة.
هل أتقنت الفئات؟ شاركنا في التعليقات!
الدوال في TypeScript — دليل شامل Functions 2026
الأدوية (Generics) في TypeScript — دليل شامل 2026
📚 مقالات ذات صلة
مشروع Node.js مع TypeScript — API كامل 2026
مشروع عملي لبناء API كامل بـ Node.js و Express و TypeScript — خطوة بخطوة مع الكود الكامل والشرح
مشروع React مع TypeScript — تطبيق مهام كامل 2026
مشروع عملي لبناء تطبيق مهام (Todo App) بـ React و TypeScript — خطوة بخطوة مع الكود الكامل والشرح
الأنواع المتقدمة في TypeScript — دليل شامل 2026
دليل عملي مفصل للأنواع المتقدمة في TypeScript — Union, Intersection, Conditional, Mapped, Template Literal، مع تمارين وحلول