TypeScript: ملفات إعلانات TypeScript
آخر تحديث: 2026-08-26
تُعد ملفات الإعلانات (.d.ts) بمثابة جسر يربط بين عالمي TypeScript وJavaScript — فهي توفر تعريفات الأنواع لشفرة JavaScript التي تفتقر إلى معلومات الأنواع، مما يتيح لك استخدام أي مكتبة JavaScript بأمان في مشاريع TypeScript الخاصة بك.
1. ما هو ملف الإعلان؟
(1) المشكلة: مكتبة JS تفتقر إلى الأنواع
TYPESCRIPT
// Usage lodash —— A pure JavaScript library
import _ from "lodash";
// ❌ TypeScript Error: Module not found "lodash" Statement Document
let result = _.chunk([1, 2, 3, 4], 2);
(2) الحل: يوفر ملف الإعلان معلومات عن الأنواع
تحمل ملفات الإعلانات اللاحقة .d.ts وتحتوي على إعلانات الأنواع فقط؛ ولا تتضمن أي كود للتنفيذ:
TYPESCRIPT
// lodash.d.ts —— Statement(Describe only the type,No implementation provided)
declare module "lodash" {
export function chunk<T>(array: T[], size: number): T[][];
export function debounce(func: Function, wait: number): Function;
// ... Additional Statements
}
بفضل ملف الإعلان، يمكن لـ TypeScript فهم واجهة برمجة تطبيقات lodash وتوفير التحقق من الأنواع وتقديم تلميحات حول الكود.
(3) المصادر الثلاثة لوثائق الإعلان
| المصدر | الوصف | مثال |
|---|---|---|
| الإعلانات المدمجة | مضمنة في TypeScript (DOM، ES2020، إلخ) | lib.dom.d.ts |
| المضمن في الحزمة | قام مؤلف المكتبة بتضمين .d.ts |
axios/index.d.ts |
| DefinitelyTyped | إعلانات الجهات الخارجية التي يديرها المجتمع | @types/lodash |
2. تثبيت حزمة @types واستخدامها
(1) البحث عن إعلانات الأنواع
BASH
# Check if a package has @types Statement
npm info @types/lodash
# Installation Type Declaration
npm install @types/lodash --save-dev
(2) النتيجة بعد التثبيت
TYPESCRIPT
// After installing @types/lodash — full type support
import _ from "lodash";
let chunks: number[][] = _.chunk([1, 2, 3, 4], 2); // ✅ Type Safety
let debounced = _.debounce(() => {}, 300); // ✅ Auto-Complete
(3) حزم @types الشائعة
| اسم الحزمة | المكتبة المقابلة |
|---|---|
@types/node |
Node.js |
@types/lodash |
Lodash |
@types/express |
Express |
@types/jest |
إنه |
@types/react |
React |
@types/jquery |
jQuery |
(4) الاكتشاف التلقائي لإعلانات الأنواع
يبحث TypeScript عن إعلانات الأنواع بالترتيب التالي:
index.d.tsفي الحزمة (نوع مدمج)- بيان بموجب
node_modules/@types/ - المواقع المحددة في
tsconfig.jsonوtypeRootsوtypes
3. اكتب ملف الإعلان الخاص بك
(1) تعريف المتغيرات العالمية
عند استيراد مكتبة JavaScript باستخدام العلامة script، يتعين عليك تعريف المتغيرات العالمية:
TYPESCRIPT
// globals.d.ts
declare var jQuery: (selector: string) => HTMLElement;
declare var $: typeof jQuery;
// Usage
let el = $(".container"); // ✅ Type Safety
(2) إعلانات الدوال العالمية
TYPESCRIPT
// globals.d.ts
declare function ga(command: string, ...args: any[]): void;
declare function gtag(type: string, eventName: string, params?: Record<string, any>): void;
// Usage
ga("send", "pageview"); // ✅
gtag("event", "click", { value: 1 }); // ✅
(3) إعلان الوحدة النمطية
عند استخدام حزم npm غير المحددة النوع، قم بتعريف الوحدة النمطية على النحو التالي:
TYPESCRIPT
// declarations.d.ts
declare module "untyped-lib" {
export function doSomething(value: string): number;
export const version: string;
export default class Client {
constructor(options: { host: string; port: number });
connect(): Promise<void>;
}
}
// Usage
import Client, { doSomething, version } from "untyped-lib";
(4) امتدادات الوحدات النمطية — إضافة أنواع إلى الوحدات النمطية الموجودة
TYPESCRIPT
// Extensions express Module
declare module "express" {
interface Request {
user?: {
id: number;
name: string;
};
}
}
// It is now available at express.Request Safety Guidelines user Properties
import { Request } from "express";
function handler(req: Request) {
if (req.user) {
console.log(req.user.name); // ✅ Type Safety
}
}
▶ مثال: كتابة إعلان لأداة JavaScript مخصصة
TYPESCRIPT
// Suppose there is a legacy-utils.js The file has no type
// legacy-utils.d.ts —— Write a statement for it
declare module "legacy-utils" {
/**
* Format the date according to the specified pattern
* @param date - Date object or timestamp
* @param pattern - Format patterns, e.g. "YYYY-MM-DD"
*/
export function formatDate(date: Date | number, pattern: string): string;
/**
* Deep-copy objects
*/
export function deepClone<T>(obj: T): T;
/**
* Image Stabilization Function
*/
export function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void;
/**
* Default Export:Toolset Object
*/
const utils: {
formatDate: typeof formatDate;
deepClone: typeof deepClone;
debounce: typeof debounce;
};
export default utils;
}
// Usage——Full Type Support
import utils from "legacy-utils";
let dateStr = utils.formatDate(new Date(), "YYYY-MM-DD");
let cloned = utils.deepClone({ name: "Charlie" });
let debounced = utils.debounce((x: number) => console.log(x), 300);
الناتج:
TEXT
📖 للعرض فقط
// Executed successfully
4. قواعد كتابة ملفات الإعلانات
(1) القواعد الأساسية
.d.tsلا يحتوي الملف إلا على إعلانات؛ ولا يتضمن أي تنفيذ.- استخدم الكلمة الرئيسية
declareلإعلان كيان خارجي exportليس مطلوبًا — ما لم يرد في إعلان الوحدة النمطية- المستوى الأعلى
exportيجعل الملف إعلان وحدة نمطية (بدلاً من إعلان عام)
(2) ثلاثة أنواع من نطاق الإعلان
TYPESCRIPT
// ── Global Declarations(None import/export) ──
// All declarations in the file are automatically visible throughout the entire project.
declare var GLOBAL_CONFIG: { api: string };
declare function globalHelper(): void;
// ── Module Declaration ──
declare module "my-lib" {
export function helper(): void;
}
// ── File Module Declaration ──
// At the top of the document, there is import/export → The entire file is a module
import { User } from "./types";
export declare function processUser(user: User): void;
(3) إرشادات حول تصدير الأنواع
TYPESCRIPT
// ✅ Recommendations——Export Interfaces and Types
export interface User {
id: number;
name: string;
}
export type UserId = number;
// ✅ Recommendations——Exported Function Signatures
export declare function getUser(id: number): User;
// ❌ Not recommended——Export the specific implementation(.d.ts Should not be implemented)
// export function getUser(id: number): User { return ...; }
5. تكوين الأنواع في ملف tsconfig
(1) typeRoots — يحدد الدليل الخاص بإعلانات الأنواع
JSON
{
"compilerOptions": {
"typeRoots": [
"./node_modules/@types",
"./src/types"
]
}
}
(2) الأنواع — حدد حزم الأنواع المراد تضمينها
JSON
{
"compilerOptions": {
"types": ["node", "jest", "lodash"]
// Includes only these three @types packages, ignoring the rest
}
}
(3) ثلاثة خيارات للصرامة
JSON
{
"compilerOptions": {
"noImplicitAny": true, // Implicit is prohibited any
"strict": true, // Enable all strict checks
"skipLibCheck": true // Skip .d.ts File Type Validation(Speed up compilation)
}
}
▶ مثال: إعلان الأنواع العامة في ملف .d.ts
الناتج:
TEXT
📖 للعرض فقط
10
30
TYPESCRIPT
// env.d.ts — declare global constants and types
declare var APP_VERSION: string;
declare var API_BASE_URL: string;
interface AppWindow extends Window {
appConfig: {
theme: "light" | "dark";
locale: string;
};
}
// Usage in any .ts file
console.log(`v${APP_VERSION}`);
console.log(APP_VERSION);
الناتج:
TEXT
📖 للعرض فقط
10
30
▶ مثال: توسيع الأنواع المضمنة بإعلان الوحدة
الناتج:
TEXT
📖 للعرض فقط
10
30
TYPESCRIPT
// array-ext.d.ts — add a method to the built-in Array type
interface Array<T> {
last(): T | undefined;
first(): T | undefined;
}
// Now every array has .last() and .first() with full type safety
let items = [10, 20, 30];
let first = items.first(); // number | undefined
let last = items.last(); // number | undefined
console.log(first); // 10
console.log(last); // 30
الناتج:
TEXT
📖 للعرض فقط
10
30
❓ أسئلة شائعة
س متى تحتاج إلى كتابة ملف إعلان؟
ج هناك ثلاث حالات: (1) مكتبة جافا سكريبت التي تستخدمها لا تحتوي على حزمة @types؛ (2) المتغيرات العالمية المستوردة عبر علامة
script؛ (3) تحتاج إلى إضافة خصائص مخصصة إلى وحدة نمطية موجودة بالفعل. في معظم الحالات، يكفي تثبيت @types؛ أما كتابة ملف إعلان خاص بك فهي ممارسة نادرة نسبيًا.س ما الفرق بين
declare module وdeclare global؟ج
declare module "xxx" يُعلن عن نوع الوحدة النمطية الخارجية — ويُستخدم لتوفير الأنواع لحزم npm. declare global يضيف إعلانًا إلى مساحة الأسماء العالمية داخل ملف الوحدة النمطية — ويُستخدم لتوسيع الأنواع العالمية (مثل Window). ويختلف نطاق كل منهما: module على مستوى الوحدة النمطية، بينما global على المستوى العالمي.س أيهما له الأسبقية — حزمة @types أم الأنواع المضمنة في المكتبة؟
ج الأنواع المضمنة في المكتبة لها الأسبقية. تتضمن المكتبات الحديثة (مثل axios و zod) بالفعل
index.d.ts داخل الحزمة، لذا لا داعي لتثبيت @types بشكل منفصل. لن تحتاج إلى @types إلا عندما لا تتضمن المكتبة أنواعها الخاصة. إذا كان كلاهما موجودًا، فسيعطي TypeScript الأولوية للإعلانات المضمنة في الحزمة.س هل ينبغي تمكين skipLibCheck؟
ج نوصي بتمكينه. تعمل ميزة skipLibCheck على تخطي فحص الأنواع لجميع ملفات
.d.ts، مما قد يؤدي إلى تسريع عملية الترجمة بشكل كبير (خاصةً في المشاريع الكبيرة). الجانب السلبي هو أنها قد تتجاهل أخطاءً في إعلانات الأنواع الخاصة بأطراف ثالثة — لكن هذا الخطر ضئيل للغاية لأن حزمة @types تخضع لمراجعة المجتمع. وتفوق مزايا الأداء هذه المخاطر بكثير.📖 ملخص
- يوفر ملف الإعلان
.d.tsمعلومات عن أنواع كود جافا سكريبت — فهو يحتوي على إعلانات فقط، دون أي تنفيذ - ثلاثة مصادر لإعلانات الأنواع: الأنواع المضمنة في TypeScript، والأنواع التي توفرها المكتبات، وحزم @types التي يقدمها المجتمع
- تثبيت إعلانات الأنواع الخاصة بأطراف ثالثة باستخدام
npm install @types/package-name - الحالات التي تكتب فيها ملفات الإعلان الخاصة بك: مكتبات جافا سكريبت غير المحددة النوع، والمتغيرات العالمية، وامتدادات الوحدات النمطية
declareيُعلن عن كيان خارجي باستخدام كلمة رئيسية؛declare moduleيُعلن عن نوع وحدة نمطية- يتحكم الإعداد
typeRoots/types/noImplicitAny/skipLibCheckالموجود فيtsconfigفي تحديد الأنواع ومستوى الصرامة
📝 تمارين
- المسألة الأساسية (الصعوبة ⭐): اكتب ملف إعلان لمكتبة جافا سكريبت افتراضية
math-helpersتتضمنadd(a, b)وsubtract(a, b)والثابتPI. - مشكلة متقدمة (درجة الصعوبة ⭐⭐): اكتب ملف إعلان يوسع واجهة
Stringويضيف الأسلوبreverse(): string. فكر في الأمر: لماذا يجب وضع توسيع النوع المدمج في ملف.d.ts؟ - التحدي (الصعوبة: ⭐⭐⭐): اكتب ملف إعلان كامل لـ SDK قديم لـ JavaScript غير محدد النوع — يتضمن مساحة أسماء
SDK، وفئةSDK.Client(منشئ + طرق)، وتعدادSDK.EventType، ودالة عامةSDK.init(options).