Menu
flag Ar iconالعربيةdown icon

الوضع الصارم في TypeScript: ما الذي يفعّله strict: true

الخيار strict: true في tsconfig.json يفعّل مجموعة من فحوص الأنواع: noImplicitAny وstrictNullChecks وstrictPropertyInitialization وخمسة غيرها. تعرّف على ما يكتشفه كل منها، وكيف تفعّل الوضع الصارم في مشروع قائم، والخيارات المفيدة التي لا يتضمنها strict.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

الوضع الصارم هو الخيار "strict": true في tsconfig.json. إنه مفتاح واحد لثمانية خيارات لفحص الأنواع تكتشف any الضمني، وnull وundefined غير المفحوصين، وإسناد الدوال غير الآمن، وحقول الأصناف غير المهيأة. في TypeScript 7 يكون strict مفعّلًا افتراضيًا. هكذا يبدو الكود الذي يجتازه:

الناتج هو no user وSyntaxError و42. احذف : number أو ?. أو فحص instanceof ولن يُترجم الملف بعدها.

تفعيله

{
    "compilerOptions": {
        "strict": true
    }
}

الخيارات الفردية تتقدم على strict في الاتجاهين. "strict": true, "strictNullChecks": false يُبقي كل شيء عدا فحص null؛ و"strict": false, "noImplicitAny": true يفعّل ذلك الخيار وحده. ويضمّك strict أيضًا إلى الفحوص التي تُضاف في الإصدارات المقبلة، لأن خيارات عائلة strict الجديدة تنضم إلى المجموعة.

لا علاقة لـ strict في TypeScript بالتوجيه "use strict" في JavaScript، وهو وضع وقت تشغيل. يُخرج TypeScript 7 دائمًا "use strict" حيث يلزم، وضبط alwaysStrict: false هو الخطأ TS5108 (أُزيل الخيار).

ما يكتشفه كل خيار

الخيارما يبلّغ عنهالخطأ
noImplicitAnyمعامل أو متغير سيكون نوعه any بصمتTS7006 Parameter 'x' implicitly has an 'any' type.
strictNullChecksاستخدام قيمة قد تكون null أو undefinedTS18048 'u' is possibly 'undefined'.
strictFunctionTypesإسناد دالة نوع معاملها أضيق من المطلوبTS2322
strictBindCallApplyوسائط خاطئة لـ .call و.bind و.applyTS2345
strictPropertyInitializationحقل صنف لا يُسند إليه أي قيمة أبدًاTS2564 Property 'name' has no initializer and is not definitely assigned in the constructor.
noImplicitThisthis بنوع any ضمني، كما في function متداخلةTS2683
useUnknownInCatchVariablesاستخدام متغير catch قبل تضييقه (نوعه unknown)TS18046 'err' is of type 'unknown'.
strictBuiltinIteratorReturnمعاملة it.next().value لمكرر مدمج كأنه معرّف دائمًاTS2322

الخياران اللذان يغيّران أكبر قدر من الكود هما noImplicitAny وstrictNullChecks. هذه الكتلة تخالف كليهما عمدًا:

تطبع index.ts(2,17): error TS7006: Parameter 'x' implicitly has an 'any' type. وindex.ts(11,13): error TS18048: 'user' is possibly 'undefined'. دون strict يُترجم هذا الكود ثم ينهار وقت التشغيل مع TypeError: Cannot read properties of undefined (reading 'name'). ومع strict يصبح الانهيار خطأ ترجمة. والإصلاحات هي الكتلة الأولى في هذه الصفحة.

strictFunctionTypes: لماذا يوجد

الدالة التي تتعامل مع النصوص فقط يجب ألا تُستخدم حيث يمكن أن تصل أرقام. الفحص في المثال التالي مُسكت بـ @ts-expect-error حتى تستطيع تشغيله ورؤية ما يمنعه الخطأ:

دون التعليق يكون الإسناد الخطأ TS2322، Type '(s: string) => void' is not assignable to type 'Handler'.، يليه Types of parameters 's' and 'value' are incompatible. يبقى استثناء واحد مقصود: معاملات الدوال المعرّفة بصياغة method (handle(value: string | number): void داخل interface) ما زالت تُفحص بالطريقة الأكثر تساهلًا، لذلك يمكن إسناد shout إلى دالة كهذه دون خطأ.

strictPropertyInitialization

يجب أن يحصل كل حقل في الصنف على قيمة في تعريفه أو في المُنشئ. ثلاث طرق لتحقيق ذلك:

الناتج:

Account {
  owner: 'Ada',
  balance: 0,
  history: [],
  lastLogin: undefined,
  sessionId: 's-1'
}

الخاصيتان lastLogin وsessionId موجودتان بالقيمة undefined لأن حقول الأصناف حقول JavaScript حقيقية عند target ES2022. تزيل علامة ! الفحص دون أن تضيف أي حماية وقت التشغيل، لذلك فضّل الأشكال الأخرى. يحتاج هذا الخيار إلى strictNullChecks؛ وإيقاف الأخير يعطّله أيضًا.

تفعيل Strict في مشروع قائم

تحويل قاعدة كود كبيرة إلى strict دفعة واحدة قد ينتج مئات الأخطاء. ولأن strict هو الإعداد الافتراضي في TypeScript 7، فترقية مشروع لم يذكر ملف tsconfig.json فيه strict أبدًا تفعّله تلقائيًا؛ اكتب "strict": false إذا احتجت إلى السلوك القديم أثناء النقل. طريق يُبقي البناء ناجحًا:

  1. أضف "strict": true وأوقف الخيارات التي فيها أكثر الأخطاء، وهي عادة "strictNullChecks": false و"noImplicitAny": false.
  2. أصلح الأخطاء المتبقية، ثم فعّل خيارًا آخر وكرر.
  3. في noImplicitAny معظم الإصلاحات تحديد أنواع للمعاملات. وفي strictNullChecks أضف | undefined حيث يمكن أن تغيب القيم، ثم تعامل معها بـ ?. أو ?? أو فحص if.
  4. حيث يجب أن ينتظر الإصلاح، ضع // @ts-expect-error مع سبب على السطر. بخلاف @ts-ignore يبلّغ عن خطأ حالما تزول المشكلة، فتتقلص القائمة من تلقاء نفسها.

لا تلجأ إلى as any أو ! لإسكات الأخطاء بالجملة: كل واحد منها يخفي بالضبط الخطأ البرمجي الذي أُضيف الخيار لاكتشافه.

خيارات مفيدة لا يتضمنها Strict

هذه الخيارات منفصلة لأنها ترفض كودًا يكون صحيحًا في أحيان كثيرة. وكثير من المشاريع تفعّلها مع ذلك.

الخيارما يفعله
noUncheckedIndexedAccessيتضمن نوع arr[i] وrecord[key] القيمة undefined
exactOptionalPropertyTypesيقبل debug?: boolean غياب المفتاح لكنه لا يقبل debug: undefined
noImplicitReturnsيجب أن يعيد كل مسار في دالة لها قيمة إعادة قيمةً (TS7030)
noImplicitOverrideيجب أن تحمل الدالة التي تعيد تعريف دالة الصنف الأساسي override (TS4114)
noFallthroughCasesInSwitchيجب أن ينتهي كل case غير فارغ بـ break أو return أو throw (TS7029)
noUnusedLocals، noUnusedParametersالمتغيرات والمعاملات غير المستخدمة أخطاء
noPropertyAccessFromIndexSignatureالمفاتيح القادمة من index signature يجب أن تستخدم obj["key"]، لا obj.key

الخيار noUncheckedIndexedAccess هو الذي يكتشف أكثر الأخطاء البرمجية الحقيقية. عند تفعيله:

const scores = [90, 85];
const d: Record<string, number> = {};

const third: number = scores[2]; // error TS2322: Type 'number | undefined' is not assignable to type 'number'.
const c: number = d["x"];        // same error

const safe = scores[2] ?? 0;     // number
for (const s of scores) {        // for...of is not affected: s is number
    console.log(s);
}

يفعّل tsc --init في TypeScript 7 الخيارين noUncheckedIndexedAccess وexactOptionalPropertyTypes في الإعداد الذي يولّده، بجانب strict.

الأسئلة الشائعة

ماذا يفعل الوضع الصارم في TypeScript؟

يفعّل "strict": true مجموعة من الفحوص الأشد: noImplicitAny وstrictNullChecks وstrictFunctionTypes وstrictBindCallApply وstrictPropertyInitialization وnoImplicitThis وuseUnknownInCatchVariables وstrictBuiltinIteratorReturn. معًا تمنع ظهور any بصمت، وتجعل null وundefined جزءًا من نظام الأنواع.

هل الوضع الصارم مفعّل افتراضيًا في TypeScript؟

في TypeScript 7 نعم: القيمة الافتراضية لـ strict هي true، لذلك يحصل المشروع الذي لا يحدد strict على كل الفحوص الصارمة. ويكتب tsc --init أيضًا "strict": true صراحة. وللتخلي عنه عليك أن تكتب "strict": false.

هل يمكن إيقاف فحص صارم واحد مع إبقاء البقية؟

نعم. الخيارات الفردية تتقدم على strict: { "strict": true, "strictNullChecks": false } يُبقي كل الفحوص الصارمة عدا فحص null. وهذه هي الطريقة المعتادة لنقل قاعدة كود كبيرة خيارًا بعد خيار.

هل الوضع الصارم في TypeScript هو نفسه "use strict" في JavaScript؟

لا. "use strict" وضع وقت تشغيل في JavaScript يغيّر سلوك الكود. أما strict في TypeScript فيغيّر فقط ما يبلّغ عنه مدقق الأنواع. يُخرج TypeScript 7 دائمًا "use strict" للناتج الذي ليس وحدة، وalwaysStrict: false أصبح خيارًا مُزالًا.

هل يتضمن strict الخيار noUncheckedIndexedAccess؟

لا. noUncheckedIndexedAccess وexactOptionalPropertyTypes وnoImplicitReturns وnoImplicitOverride وnoFallthroughCasesInSwitch خيارات مستقلة تفعّلها بنفسك. ويفعّل tsc --init أول اثنين منها في الإعداد الذي يولّده.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن