Vue.js: TypeScript: أفضل الممارسات

آخر تحديث: 2026-08-26

تعد TypeScript هي المعيار لمشاريع Vue 3 على مستوى المؤسسات — فهي توفر أمان الأنواع، والإكمال التلقائي في بيئة تطوير المتكاملة (IDE)، والثقة في إعادة هيكلة الكود. وترتقي ميزة <script setup lang="ts"> في Vue 3.4+ بتكامل TypeScript إلى آفاق جديدة: الاستدلال التلقائي لـ defineProps وdefineEmits، وأنواع مرجعية مثالية للمكونات.

إتقان لغة Vue و TypeScript هو المفتاح للتقدم من مطور مبتدئ إلى مطور متقدم. ستساعدك هذه الدورة التدريبية على بناء قاعدة معرفية شاملة حول Vue 3 و TypeScript.

1. ما ستتعلمه



2. كابوس «indefinido ليس دالة» في مشروع جافا سكريبت

(1) المشكلة: 100 خطأ من نوع «indefinido» في مشروع جافا سكريبت

كان نظام إدارة أليس مكتوبًا في الأصل بلغة جافا سكريبت. الأخطاء الشائعة:

JS
// ❌ The "Broken" Version:JS Errors are not detected until runtime
export default {
  props: {
    user: { type: Object, required: true }
    // Misspelled prop name: userName (No errors)
    // prop Wrong type:No errors
    // emit The event name is incorrect:No errors
  }
}
VUE
<!-- The parent component uses userName,However, the child component defines user -->
<UserCard userName="Alice" />  <!-- ❌ I didn't realize it until runtime -->

<!-- emit The event name is incorrect -->
<Child @updae="handler" />  <!-- ❌ I didn't realize it until runtime -->

يتم الكشف عن أكثر من 100 خطأ محتمل فقط أثناء وقت التشغيل، مما يؤدي إلى ارتفاع تكاليف تصحيح الأخطاء.

(2) حل باستخدام Vue 3 و TypeScript

VUE
<!-- Child component:UserCard.vue -->
<script setup lang="ts">
interface User {
  id: number
  name: string
  email: string
}

const props = defineProps<{
  user: User
  variant?: 'primary' | 'secondary'
}>()

const emit = defineEmits<{
  select: [userId: number]
  delete: [userId: number]
}>()
</script>
VUE
<!-- Using Parent Components:An error occurs during compilation -->
<UserCard :user="alice" />  <!-- ✅ Compile-Time Type Checking -->
<UserCard @updae="handler" />  <!-- ❌ TS Error: The event does not exist. -->

يتم اكتشاف جميع الأخطاء أثناء التحويل البرمجي، ويقوم بيئة التطوير المتكاملة (IDE) بتمييزها باللون الأحمر.

(3) الإيرادات

بعد إضافة TypeScript:



3. الإعدادات الأساسية لـ TypeScript

(1) إعداد البرنامج النصي lang="ts"

VUE
<template>
  <p>{{ count }}</p>
  <button @click="increment">+</button>
</template>

<script setup lang="ts">
import { ref } from 'vue'

// ✅ TS Automatic Inference:Ref<number>
const count = ref(0)

// ✅ Parameters and Return Types
function increment(): void {
  count.value++
}
</script>

(2) أساسيات ملف tsconfig.json

JSON
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue"
  ]
}

(3) أفضل 5 تكوينات موصى بها

JSON
{
  "compilerOptions": {
    // 1. Strict Mode(Guaranteed to Open)
    "strict": true,
    
    // 2. No implicit any
    "noImplicitAny": true,
    
    // 3. Strict Null Checks
    "strictNullChecks": true,
    
    // 4. Strict Function Types
    "strictFunctionTypes": true,
    
    // 5. Strictly Bounded Calls
    "strictBindCallApply": true
  }
}


4. 5 طرق لكتابة defineProps باستخدام الأنواع العامة

(1) الطريقة الأولى: الأنواع الأولية

TS
const props = defineProps<{
  name: string
  age: number
  active: boolean
}>()

(2) الطريقة الثانية: اختياري + القيمة الافتراضية

TS
// withDefaults Provide a default value
const props = withDefaults(defineProps<{
  name: string
  age?: number
  variant?: 'primary' | 'secondary'
}>(), {
  age: 18,
  variant: 'primary'
})

(3) النهج الثالث: الكائنات المعقدة / المصفوفات

TS
interface User {
  id: number
  name: string
  email: string
}

const props = defineProps<{
  user: User
  items: User[]
  config: Record<string, unknown>
}>()

(4) النهج 4: الدالة prop

TS
const props = defineProps<{
  formatter: (value: number) => string
  onChange: (value: string) => void
}>()

(5) النهج الخامس: المكونات العامة

TS
// Generic Components:List<T> Can be specified item Type
<script setup lang="ts" generic="T extends { id: number }">
defineProps<{
  items: T[]
  selected?: T
}>()
</script>

<!-- Usage -->
<List :items="users" />  <!-- T = User -->
<List :items="products" />  <!-- T = Product -->


5. النوع defineEmits

(1) 5 أنواع من عبارات الأحداث

TS
// 1. Simple Events
const emit = defineEmits<{
  click: []
  submit: []
}>()

// 2. Single parameter
const emit = defineEmits<{
  select: [id: number]
  delete: [id: number]
}>()

// 3. Multi-parameter
const emit = defineEmits<{
  change: [id: number, oldValue: string, newValue: string]
}>()

// 4. Optional Parameters
const emit = defineEmits<{
  search: [query?: string]
  load: [id: number, options?: object]
}>()

// 5. void Return Value
const emit = defineEmits<{
  success: [data: object]
  error: [message: string]
}>()

(2) الأحداث المُحفِّزة

TS
const emit = defineEmits<{
  select: [id: number]
  delete: [id: number]
}>()

// ✅ TypeScript Check Parameter Types
emit('select', 123)  // ✅ OK
emit('select', 'abc')  // ❌ TS Error
emit('delete', 456)

(3) استخدام المكون الأصلي

VUE
<template>
  <!-- ✅ TS Check Event Name -->
  <Child @select="handleSelect" @delete="handleDelete" />
  <!-- ❌ TS Error:The event does not exist. -->
  <!-- <Child @updae="handler" /> -->
</template>

<script setup lang="ts">
function handleSelect(id: number) {
  console.log('Selected:', id)
}
</script>


6. الأنواع المرجعية / التفاعلية / المحسوبة

(1) استدلال النوع لـ ref

TS
import { ref } from 'vue'

// Automatically inferred as Ref<number>
const count = ref(0)
count.value = 1  // ✅

// Inferred as Ref<string>
const name = ref('Alice')

// Inferred as Ref<number | undefined>(It could be undefined)
const maybeNumber = ref<number>()
maybeNumber.value  // type: number | undefined

(2) الاستدلال التفاعلي على الأنواع

TS
import { reactive } from 'vue'

// Automatic Inference
const state = reactive({
  count: 0,
  user: { name: 'Alice', age: 25 }
})

state.count  // type: number
state.user.name  // type: string

// Explicit Type
interface State {
  count: number
  items: string[]
}
const s = reactive<State>({
  count: 0,
  items: []
})

(3) الأنواع المحسوبة

TS
import { ref, computed } from 'vue'

const count = ref(10)

// Automatic Inference:ComputedRef<number>
const double = computed(() => count.value * 2)

// Explicit Type
const formatted = computed<string>(() => `Count: ${count.value}`)


7. أنواع المراجع للمكونات (useTemplateRef)

(1) العرض 3.5+ باستخدام useTemplateRef

VUE
<template>
  <input ref="usernameInput">
  <MyChart ref="chartComponent" :data="chartData" />
</template>

<script setup lang="ts">
import { useTemplateRef, onMounted } from 'vue'
import MyChart from './MyChart.vue'

// ✅ TS Automatic Inference:Ref<HTMLInputElement | null>
const inputRef = useTemplateRef<HTMLInputElement>('usernameInput')

// ✅ Component Instance Types
const chartRef = useTemplateRef<InstanceType<typeof MyChart>>('chartComponent')

onMounted(() => {
  inputRef.value?.focus()  // TS Auto-Complete
  chartRef.value?.refresh()
})
</script>

(2) Vue 3.4 — الصيغة القديمة

TS
// Old notation:Must be done manually ref<>
import { ref, onMounted } from 'vue'
import MyChart from './MyChart.vue'

const inputRef = ref<HTMLInputElement | null>(null)
const chartRef = ref<InstanceType<typeof MyChart> | null>(null)


8. الإعدادات المتقدمة لـ Volar

(1) التثبيت

BASH
# VS Code Install "Vue - Official" Extensions(Volar)
# Search:Vue - Official

(2) ملف settings.json الموصى به

JSON
{
  "vue.enabled.volar": true,
  "vue.compilerOptions.target": 3.4,
  "vue.complete.casing.tags": ["PascalCase", "snake_case"],
  
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.preferences.includePackageJsonAutoImports": "on",
  
  "editor.formatOnSave": true,
  "[vue]": {
    "editor.defaultFormatter": "Vue.volar"
  }
}

(3) 5 سمات رئيسية للوجه الفولاري

الميزة الوصف
استدلال الأنواع الاستدلال التام للـ props و emits و refs
الإكمال التلقائي اقتراحات ذكية لأسماء المكونات وخصائصها وعمليات الإرسال
التحقق من الأخطاء الأخطاء التي تظهر أثناء التحويل البرمجي (مثل نوع الخاصية غير الصحيح)
الانتقال إلى التعريف F12 الانتقال إلى تعريف المكون
دعم إعادة الهيكلة إعادة تسمية خاصية (prop) لمزامنة جميع الإشارات إليها تلقائيًا


9. أمثلة كاملة: 5 أنماط رئيسية لـ TS

▶ مثال: 1. 5 طرق لكتابة defineProps

TS
// 1. Basics
defineProps<{ name: string }>()

// 2. Optional+Default
withDefaults(defineProps<{ name?: string }>(), { name: 'Guest' })

// 3. Complex
defineProps<{ user: User; items: User[] }>()

// 4. Function
defineProps<{ onClick: () => void }>()

// 5. Generics
defineProps<{ items: T[] }>()  // Needs generic="T"
▶ جرّب الكود

▶ مثال: 2. defineEmits 5 أحداث

TS
// 1. Simple
defineEmits<{ click: [] }>()

// 2. Single Parameter
defineEmits<{ select: [id: number] }>()

// 3. More information
defineEmits<{ change: [old: string, new: string] }>()

// 4. Optional
defineEmits<{ search: [q?: string] }>()

// 5. void
defineEmits<{ done: [] }>()
▶ جرّب الكود

▶ مثال: 3. 5 أخطاء شائعة في TS

TS
// 1. Property 'x' does not exist
// → Check Spelling,or add a type

// 2. Argument of type 'X' is not assignable
// → Type mismatch,Check Parameter Types

// 3. Type 'X' is not assignable to type 'Y | null'
// → Strict Null Checks, Add ! or ?

// 4. Cannot find module './X'
// → Path error,Check Import

// 5. Object is possibly 'undefined'
// → Optional Chain ?.
▶ جرّب الكود

▶ مثال: 4. 5 مقارنات رئيسية في الأداء

النمط أمان الأنواع الأداء قابلية التطبيق
JS ⭐⭐⭐⭐⭐ نموذج أولي/مشروع صغير
TS (أساسي) ⭐⭐⭐ ⭐⭐⭐⭐ عام
TS (صارم) ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ مشاريع المؤسسات
TS + Volar ⭐⭐⭐⭐⭐ ⭐⭐⭐ موصى به
إصدار TS + tsc ⭐⭐⭐⭐⭐ ⭐⭐⭐ المشاريع واسعة النطاق

▶ مثال: 5. 5 هياكل رئيسية لمشاريع Vue 3 + TS

TEXT 📖 للعرض فقط
src/
├-- components/        # Public Components
│   ├-- UserCard.vue   # <script setup lang="ts">
│   └-- BaseButton.vue
├-- views/             # Page Components
├-- stores/            # Pinia(TS)
├-- composables/       # Composables
├-- types/             # Type Definitions
│   ├-- user.ts        # export interface User
│   ├-- api.ts         # export interface ApiResponse<T>
│   └-- index.ts       # Batch Export
├-- utils/             # Utility Functions
├-- router/            # Routing(TS)
├-- App.vue
└-- main.ts            # Entrance

▶ مثال: 6. 5 مرجع سريع للأخطاء الشائعة

الخطأ الأعراض الحل
اسم متغير به خطأ إملائي خطأ في التجميع استخدم بيئة التطوير المتكاملة (IDE) للانتقال إلى التعريف
خطأ إملائي في كلمة "emit" خطأ في التجميع استخدم النوع "defineEmits"
فشل تحويل النوع خطأ في الترجمة استخدم تأكيد النوع أو الأنواع العامة
القيمة المرجعية غير محددة وقت التشغيل التسلسل الاختياري ?.
مرجع دائري للنوع خطأ في التجميع استخدم استيرادًا مخصصًا للنوع فقط


❓ أسئلة شائعة

س هل أداء Vue 3 + TS أقل من أداء JS؟
ج تتم عملية التحقق من الأنواع في مرحلة التحويل البرمجي ولا تؤثر على مرحلة التشغيل (حيث يتم محو الأنواع). ويتم تحويل Volar بسرعة كبيرة، لذا فإن الفرق بالكاد يمكن ملاحظته.
س استخدام العناصر العامة defineProps أم الإعلان في وقت التشغيل؟
ج نوصي باستخدام العناصر العامة. تقوم TypeScript باستنتاج أنواع الخصائص تلقائيًا، كما توفر بيئات تطوير المتكاملة (IDE) ميزة الإكمال التلقائي الممتازة. أما الإعلانات في وقت التشغيل فتتطلب منك كتابة أدوات التحقق يدويًّا.
س كيف تكتب المكونات العامة؟
ج <script setup lang="ts" generic="T">، ثم defineProps<{ items: T[] }>(). مدعوم في Vue 3.3 والإصدارات الأحدث.
س كيف تكتب defineModel في TypeScript؟
ج const modelValue = defineModel<string>('modelValue', { default: '' }). حدد النوع باستخدام العناصر العامة.
س هل يتطلب useTemplateRef استخدام Vue 3.5 أو إصدار أحدث؟
ج نعم. بالنسبة لـ Vue 3.4 والإصدارات الأقدم، استخدم ref<HTMLInputElement | null>(null).
س هل من الضروري تمكين الوضع الصارم في ملف tsconfig.json؟
ج إنه إلزامي لمشاريع المؤسسات. يمكن للمبتدئين البدء بتعطيل الوضع الصارم ثم تمكينه تدريجيًا. موصى به: "strict": true, "noImplicitAny": true, "strictNullChecks": true.
س ما هو Volcano / vue-tsc؟
ج vue-tsc هي أداة للتحقق من أنواع TypeScript لمشاريع Vue (طورها فريق Volar). npx vue-tsc --noEmit تقوم بإجراء عمليات التحقق من الأنواع (لا تولد كود JS، بل تقتصر على التحقق من الأنواع فقط).
س هل يمكن استخدام Vue 3 مع TypeScript في SSR؟
ج نعم. يدعم Nuxt 3 لغة TypeScript بشكل مدمج. كما يدعم كل من Pinia وVue Router لغة TypeScript بشكل أصلي.

📖 ملخص


📝 تمارين

  1. أسئلة أساسية (مستوى الصعوبة: ⭐)

    تحويل مكون واحد من JS إلى TS:

    • <script setup lang="ts">
    • defineProps Generics
    • نوع defineEmits
    • تم إتمام عملية التجميع والتحقق بنجاح
  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    تنفيذ نظام أنواع TS كامل:

    • 5 واجهات (المستخدم / المنتج / الطلب / الفئة / سلة التسوق)
    • 5 مكونات تستخدم defineProps مع العناصر العامة
    • 5 مكونات من النوع defineEmits
    • الوضع الصارم لـ tsconfig
    • التكوين الفولاري
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    تنفيذ مشروع كامل باستخدام «Vue 3 + TS»:

    1. 5 متاجر (Pinia + TS)
    2. 5 مكونات قابلة للتركيب (TS)
    3. 10 مكونات (العناصر العامة + استدلال الأنواع)
    4. حلول لخمسة أخطاء شائعة في نظام TS
    5. التحقق من أنواع البيانات في vue-tsc (CI/CD)
    6. Volar + IDE: الإعداد المثالي
    7. الإنشاء التلقائي لوثائق الأنواع (typedoc)
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%