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. ما ستتعلمه
<script setup lang="ts">الأساسيات- 5 طرق لكتابة
definePropsباستخدام الأنواع العامة - تحديد نوع «emits» + قيود المعلمات
- الاستدلال على الأنواع المرجعي / التفاعلي / الحسابي
- نوع مرجع المكون (useTemplateRef)
- الإعدادات المتقدمة لـ Volar
- أفضل الممارسات الخاصة بملف tsconfig.json
- 5 أخطاء شائعة في TS
2. كابوس «indefinido ليس دالة» في مشروع جافا سكريبت
(1) المشكلة: 100 خطأ من نوع «indefinido» في مشروع جافا سكريبت
كان نظام إدارة أليس مكتوبًا في الأصل بلغة جافا سكريبت. الأخطاء الشائعة:
// ❌ 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
}
}
<!-- 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
<!-- 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>
<!-- 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:
- أخطاء وقت التشغيل: 80% → 10% (تم اعتراضها في وقت التحويل البرمجي)
- الإكمال التلقائي في بيئة تطوير التطبيقات (IDE): دقة تزيد عن 95%
- استعادة الثقة: أمان الأنواع — لا خوف من إحداث أخطاء
- التعاون بين أعضاء الفريق: واجهات واضحة وتكاليف اتصال منخفضة
3. الإعدادات الأساسية لـ TypeScript
(1) إعداد البرنامج النصي lang="ts"
<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
{
"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 تكوينات موصى بها
{
"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) الطريقة الأولى: الأنواع الأولية
const props = defineProps<{
name: string
age: number
active: boolean
}>()
(2) الطريقة الثانية: اختياري + القيمة الافتراضية
// withDefaults Provide a default value
const props = withDefaults(defineProps<{
name: string
age?: number
variant?: 'primary' | 'secondary'
}>(), {
age: 18,
variant: 'primary'
})
(3) النهج الثالث: الكائنات المعقدة / المصفوفات
interface User {
id: number
name: string
email: string
}
const props = defineProps<{
user: User
items: User[]
config: Record<string, unknown>
}>()
(4) النهج 4: الدالة prop
const props = defineProps<{
formatter: (value: number) => string
onChange: (value: string) => void
}>()
(5) النهج الخامس: المكونات العامة
// 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 أنواع من عبارات الأحداث
// 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) الأحداث المُحفِّزة
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) استخدام المكون الأصلي
<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
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) الاستدلال التفاعلي على الأنواع
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) الأنواع المحسوبة
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
<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 — الصيغة القديمة
// 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) التثبيت
# VS Code Install "Vue - Official" Extensions(Volar)
# Search:Vue - Official
(2) ملف settings.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
// 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 أحداث
// 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
// 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
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" |
| فشل تحويل النوع | خطأ في الترجمة | استخدم تأكيد النوع أو الأنواع العامة |
| القيمة المرجعية غير محددة | وقت التشغيل | التسلسل الاختياري ?. |
| مرجع دائري للنوع | خطأ في التجميع | استخدم استيرادًا مخصصًا للنوع فقط |
❓ أسئلة شائعة
defineProps أم الإعلان في وقت التشغيل؟<script setup lang="ts" generic="T">، ثم defineProps<{ items: T[] }>(). مدعوم في Vue 3.3 والإصدارات الأحدث.defineModel في TypeScript؟const modelValue = defineModel<string>('modelValue', { default: '' }). حدد النوع باستخدام العناصر العامة.useTemplateRef استخدام Vue 3.5 أو إصدار أحدث؟ref<HTMLInputElement | null>(null)."strict": true, "noImplicitAny": true, "strictNullChecks": true.npx vue-tsc --noEmit تقوم بإجراء عمليات التحقق من الأنواع (لا تولد كود JS، بل تقتصر على التحقق من الأنواع فقط).📖 ملخص
<script setup lang="ts">هو الإعداد القياسي لـ Vue 3 + TS- 5 طرق لكتابة
definePropsباستخدام الأنواع العامة: أساسية / اختيارية / معقدة / دالة / عامة - يضمن النوع
defineEmitsوقيود المعلمات صحة الأحداث - 5 توصيات: tsconfig:strict / noImplicitAny / strictNullChecks وغيرها.
- useTemplateRef (Vue 3.5+) الاستدلال التلقائي المثالي للأنواع
- يُعد «فولار» ملحقًا لا غنى عنه لـ VS Code
- 5 أخطاء شائعة: الأخطاء الإملائية / الأخطاء المطبعية / الإشارات الدائرية
📝 تمارين
-
أسئلة أساسية (مستوى الصعوبة: ⭐)
تحويل مكون واحد من JS إلى TS:
<script setup lang="ts">- defineProps Generics
- نوع defineEmits
- تم إتمام عملية التجميع والتحقق بنجاح
-
مسائل متقدمة (مستوى الصعوبة: ⭐⭐)
تنفيذ نظام أنواع TS كامل:
- 5 واجهات (المستخدم / المنتج / الطلب / الفئة / سلة التسوق)
- 5 مكونات تستخدم
definePropsمع العناصر العامة - 5 مكونات من النوع
defineEmits - الوضع الصارم لـ tsconfig
- التكوين الفولاري
-
مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)
تنفيذ مشروع كامل باستخدام «Vue 3 + TS»:
- 5 متاجر (Pinia + TS)
- 5 مكونات قابلة للتركيب (TS)
- 10 مكونات (العناصر العامة + استدلال الأنواع)
- حلول لخمسة أخطاء شائعة في نظام TS
- التحقق من أنواع البيانات في vue-tsc (CI/CD)
- Volar + IDE: الإعداد المثالي
- الإنشاء التلقائي لوثائق الأنواع (typedoc)