FreeToGenerate.com

الصق ملف tsconfig وانظر أي الفحوص مفعَّلة حقًا. يشغّل strict تسع خيارات ويترك ثمانية أخرى مطفأة، ولكلٍّ منها شفرة تمرّ من تحته. ولا يُرفع شيء.

جرِّب:
‏strict
true
الفحوص التي يغطيها strict
8 / 9
الفحوص التي لا يغطيها
0 / 8

مُطفأة يدويًا

هذه مكتوبة false في إعدادك، والتصريح يغلب strict. ولن يشتكي المترجم من أنك طلبت الأمرين معًا.

  • noImplicitAny

ما يفعّله strict

هذه التسعة بالضبط، مقروءةً من المترجم لا من مقال. وضبطها بنفسك زائد عن الحاجة إلا إن كنت تُطفئ واحدةً منها.

  • noImplicitAnyمطفأة · مضبوطة في إعدادك
  • strictNullChecksمفعَّلة · بفضل strict
  • strictFunctionTypesمفعَّلة · بفضل strict
  • strictBindCallApplyمفعَّلة · بفضل strict
  • strictPropertyInitializationمفعَّلة · بفضل strict
  • strictBuiltinIteratorReturnمفعَّلة · بفضل strict
  • noImplicitThisمفعَّلة · بفضل strict
  • useUnknownInCatchVariablesمفعَّلة · بفضل strict
  • alwaysStrictمفعَّلة · بفضل strict

ما يتركه strict

كل واحدة من هذه تلتقط ما يقبله strict. وفي كل صفّ برنامج يُترجم نظيفًا مع strict ويفشل ما إن تُفعَّل الخيار.

  • noUncheckedIndexedAccessمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS2322

    const xs: string[] = []
    const first: string = xs[0]
    export { first }
  • exactOptionalPropertyTypesمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS2375

    type User = { nickname?: string }
    const u: User = { nickname: undefined }
    export { u }
  • noImplicitOverrideمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS4114

    class Base { save() {} }
    class Row extends Base { save() {} }
    export { Row }
  • noPropertyAccessFromIndexSignatureمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS4111

    type Env = { [key: string]: string }
    declare const env: Env
    export const url = env.DATABASE_URL
  • noFallthroughCasesInSwitchمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS7029

    export function rank(n: number) {
      switch (n) {
        case 1:
          console.log("one")
        case 2:
          return 2
      }
      return 0
    }
  • noImplicitReturnsمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS7030

    export function sign(n: number) {
      if (n > 0) {
        return "positive"
      }
    }
  • noUnusedLocalsمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS6133

    export function total(n: number) {
      const unused = n * 2
      return n
    }
  • noUnusedParametersمطفأة · غير مطلوبة

    ‏strict يقبل هذا · وهذا الخيار يرفضه بالخطأ TS6133

    export function greet(name: string, title: string) {
      return name
    }
TypeScript 5.9.3

مقروء من مترجم TypeScript الذي يُبنى به هذا الموقع، فالقائمة تتبع المترجم لا العكس.

متوفر أيضًا بلغات أخرى: English · Español · Português · Français

ماذا يفعّل وضع strict في تايب سكربت فعلًا

الخيارات التسعة التي يغطيها strict، والثمانية التي لا يغطيها، والشفرة التي يمرّرها كل منها؛ مفحوصةً بالترجمة لا بالنقل.

ماذا يفعل strict: true؟

ضبط strict على true في ملف tsconfig اختصار: فهو يشغّل مجموعة ثابتة من خيارات المترجم المفردة، وليس فحصًا قائمًا بذاته. وفي تايب سكربت 5.9 تضم هذه المجموعة تسعة أعضاء بالضبط: noImplicitAny وstrictNullChecks وstrictFunctionTypes وstrictBindCallApply وstrictPropertyInitialization وstrictBuiltinIteratorReturn وnoImplicitThis وuseUnknownInCatchVariables وalwaysStrict.

ويجدر أن تقرأ هذه القائمة من المترجم لا من مقال، لأنها تنمو. فقد أُضيف strictBuiltinIteratorReturn في الإصدار 5.6، وأغلب ما يُكتب ما زال يصف strict بأنه سبعة خيارات أو ثمانية. وهذه الصفحة تأخذ القائمة من تصريحات خيارات المترجم نفسه، فتتبع تايب سكربت لا العكس.

والمهم هو ما ليس في المجموعة. فلدى تايب سكربت ثمانية خيارات أخرى تلتقط أخطاءً حقيقية ولا يمسّها strict، منها noUncheckedIndexedAccess وexactOptionalPropertyTypes وnoImplicitOverride. فالمشروع الذي فيه strict مفعَّل ليس مشروعًا فُعِّلت فيه كل الفحوص، والفجوة أوسع مما يظن أكثر الناس.

كيف تستعمله

  1. الصق ملف tsconfig، أو كتلة compilerOptions وحدها. التعليقات والفواصل الزائدة لا تضر: فملف tsconfig هو JSONC لا JSON، وهذه الصفحة تقرأه كما يقرأه tsc. ويصلح الملف كاملًا كما يصلح كائن خيارات مجرّد.
  2. اقرأ العدّادين. كم من التسعة التي يغطيها strict مفعَّلة، وكم من الثمانية التي لا يغطيها. وما أطفأته بيدك يظهر على حدة، لأن التصريح يغلب strict ولا أحد ينبّهك.
  3. وانظر أمثلة الشفرة تحت الثمانية. كل مثال برنامج يُترجم نظيفًا مع strict ويفشل ما إن يُضاف ذلك الخيار. وانسخ الإعداد الأشد صرامة من الزر إن أردت السبعة عشر كلها.

الفحوص الثمانية التي يتركها strict

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

وأول ما يصادفك noUncheckedIndexedAccess. فتحت strict، قراءة xs[0] من مصفوفة نصوص تعطيك نصًّا، حتى لو كانت المصفوفة فارغة وكانت القيمة undefined؛ أي إن الفهرسة تكذب ببساطة. وبتفعيل الخيار يصير النوع string | undefined ويبدأ المترجم يطالبك بالتحقق. وهو أكبر مصدر لقيم undefined في زمن التشغيل داخل شفرات صارمة فيما عدا ذلك.

وأدقّها exactOptionalPropertyTypes. فمع نوع { nickname?: string } يقبل strict بلا اعتراض { nickname: undefined }، فيختفي الفرق بين خاصية غائبة وأخرى حاضرة قيمتها undefined، وهذا يهمّ كثيرًا إن كان الكائن سيُسلسَل أو يُنشر على صفٍّ في قاعدة بيانات. وnoImplicitOverride يلتقط دالة في صنف فرعي تحجب دالة الأب من غير قصد، وهكذا تكفّ إعادة التسمية في صمت عن استدعاء ما ظننته. وnoPropertyAccessFromIndexSignature يردّ env.DATABASE_URL إلى env["DATABASE_URL"]، فيكفّ الخطأ الإملائي في اسم متغير بيئة عن المرور بوصفه نصًّا.

أما الأربعة الباقية فشأنها بالشفرة الميتة أو غير القابلة للوصول أكثر من شأنها بالأنواع: حالة switch تتسرّب إلى التي بعدها، ودالة تُرجع قيمة في مسار ولا شيء في آخر، ومتغيرات محلية أو معاملات لا يقرؤها أحد.

حدود معلنة

التصريح يغلب strict في الاتجاهين، وهذا هو الجزء الذي يعضّ في صمت. فكتابة strict على true بجانب noImplicitAny على false تُسكت فعلًا أخطاء any الضمني: يقبل المترجم هذا الجمع بلا كلمة، وقد يحمل إعدادٌ موروث عن مشروع قديم ثغرةً كهذه سنين. وهذه الصفحة تسردها على حدة، وسيؤكدها لك tsc --showConfig إن أردت رأيًا ثانيًا.

وهي لا تتبع extends. فملف tsconfig يرث من ملف أساس — إعداد إطار عمل أو حزمة مشتركة — إنما يروي نصف القصة، وهذه الصفحة تقرأ ما تلصقه بدل أن تحلّ السلسلة. شغّل tsc --showConfig في المشروع لترى النتيجة المحلولة ثم الصقها هنا.

والقائمة مرتبطة بإصدار من تايب سكربت، معروضٍ بجانب زر النسخ. فالخيارات تُضاف: وإن كان مترجمك أحدث من مترجم هذه الصفحة فقد يعرف خيارًا ليس هنا. ولهذا تُولَّد القائمة من المترجم بدل أن تُكتب يدويًا، ولهذا يظهر الإصدار على الصفحة بدل أن يُترك مضمرًا.

وأخيرًا، تفعيل كل شيء ليس صوابًا بالضرورة. فـnoUnusedLocals تحديدًا يشاكس العمل الجاري، وفرق كثيرة تبقيه في المحرر لا في البناء. وهذه الصفحة تريك أين أنت وكم يكلّف كل خيار، ولا تتظاهر بأن الجواب دائمًا نعم.

لماذا هي مجانية؟

كل شيء يجري في متصفحك. وقد يذكر ملف tsconfig مسارات داخلية ومستودعات حزم وبنية المشروع، ولا يُرسل شيء من ذلك إلى أي جهة؛ فالملف لا يغادر لسان التبويب.

ولا كلفة خادم تُستردّ، فلا حساب ولا حدّ ولا علامة مائية.