Kodokon kodokon.com

tsconfig الصارم: الخيارات الأساسية والأخطاء الشائعة

تفهم ما يُفعّله الوضع الصارم فعلا وتعرف كيف تعالج الأخطاء النموذجية التي يكشفها في مشروع قائم.

11 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

"strict": true ليس خيارا واحدا بل تجميعة تُفعّل عائلة كاملة من الفحوص: strictNullChecks وnoImplicitAny وstrictFunctionTypes وstrictBindCallApply وstrictPropertyInitialization وnoImplicitThis وuseUnknownInCatchVariables وalwaysStrict. وقد يضيف كل إصدار جديد من TypeScript المزيد: فتفعيل strict يشترككَ في الفحوص المستقبلية. ويبقى بالإمكان تعطيل كل عَلَم على حدة، ما يتيح هجرة تدريجية على قاعدة كود قائمة.

JSON
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noFallthroughCasesInSwitch": true,
    "exactOptionalPropertyTypes": true,
    "verbatimModuleSyntax": true,
    "skipLibCheck": true
  }
}
أساس صارم مُوسَّع بخيارات خارج التجميعة (ملف JSON).

أعلى العَلَمين أثرا هما strictNullChecks وnoImplicitAny. يُزيل الأول null وundefined من كل الأنواع: فكل قيمة قد تغيب يجب أن تُصرَّح T | undefined وتُعالَج قبل الاستعمال. ويرفض الثاني أن يرتد مُعامل بلا شرح إلى any. ومعا، يقضيان على العائلتين الكبيرتين من أخطاء JavaScript: "cannot read property of undefined" وانتشار القيم غير المُتحقَّق منها. ويُكمِل useUnknownInCatchVariables الصورة: متغيّر catch يصير unknown، لأن JavaScript تتيح رمي أي شيء.

TYPESCRIPT
function findPort(
  env: Record<string, string | undefined>
): number {
  const raw = env["PORT"];
  if (raw === undefined) {
    return 3000;
  }
  return Number.parseInt(raw, 10);
}

declare function riskyOperation(): void;

try {
  riskyOperation();
} catch (err) {
  const message =
    err instanceof Error ? err.message : String(err);
  console.error(message);
}
نمطان صارمان: معالجة الغياب، وcatch بوصفه unknown.

أخطاء الهجرة الشائعة وعلاجاتها الحقيقية. "Object is possibly undefined": فضّل التضييق (if)، أو التسلسل الاختياري ?.، أو قيمة افتراضية بـ?? على تأكيد عدم النُّلية !، الذي ينقل الانهيار إلى مكان آخر لا أكثر. "Property has no initializer" (strictPropertyInitialization): هيّئ في الباني بدل اللجوء إلى ! على الحقل. واحذر أيضا فخ ?? مقابل ||: فـport || 3000 يستبدل 0 و"" أيضا، بينما port ?? 3000 يستبدل null وundefined فقط.

TYPESCRIPT
interface Settings { retries?: number }

function resolveRetries(s: Settings): number {
  const bad = s.retries || 3;
  const good = s.retries ?? 3;
  return good;
}

const names = ["Ada", "Linus"];
const first = names[0];
const upper = first?.toUpperCase() ?? "N/A";
retries: 0 يعطي bad = 3 لكن good = 0؛ ويُفحَص الوصول المُفهرَس بعده.

خارج التجميعة، تستحق ثلاثة خيارات نقاشا مع الفريق. noUncheckedIndexedAccess يضيف undefined إلى كل وصول مُفهرَس (arr[i]، dict[key]): أأمن، لكنه مُسهِب في كود معالجة المصفوفات - فتعتمده فرق كثيرة على المشاريع الجديدة فقط. وexactOptionalPropertyTypes يميّز "الخاصية غائبة" عن "الخاصية مضبوطة على undefined"، وهو حاسم للفرقعات. وskipLibCheck يتخطّى فحص ملفات .d.ts لتبعياتك: مفاضلة مقصودة بين زمن البناء وكشف التعارضات بين المكتبات.

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. ماذا يفعل "strict": true بالضبط في tsconfig.json؟
    • يُفعّل خيار strictNullChecks وحده
    • يُفعّل مجموعة من الأعلام الصارمة، يمكن تعطيل كل منها على حدة
    • يمنع أي استعمال لنوع any، حتى الصريح منه
    • يفرض التصريف في وضع ES5
  2. مع retries?: number مضبوطا على 0، ما الفرق بين retries || 3 وretries ?? 3؟
    • لا فرق، كلاهما يُعيد 0
    • || يُعيد 3 لأن 0 قيمة زائفة؛ و؟؟ يُعيد 0 لأنه يستبدل null وundefined فقط
    • ؟؟ يُعيد 3 لأن 0 يُعامَل بوصفه غائبا
  3. لماذا نفضّل // @ts-expect-error على // @ts-ignore لتعليم دَين الأنواع؟
    • @ts-expect-error يقمع عدة أخطاء دفعة واحدة
    • @ts-ignore لا يعمل في الوضع الصارم
    • @ts-expect-error يصير خطأ حالما يُصلَح المشكل، فينظّف الدَّين نفسه بنفسه