it-swarm.asia

ما الفرق بين "تعريف الفئة" و "الواجهة" في TypeScript

في TypeScript ، عند إنشاء ملفات تعريف المصدر .d.ts ، ما هو الأفضل ولماذا؟

declare class Example {
    public Method(): void; 
}

أو

interface Example {
    Method(): void;
}

الاختلافات التي يمكنني تحديدها هي أن الواجهات لا يمكن أن تحتوي على أساليب ثابتة ، لذلك يجب عليك استخدام فئة لذلك. كلاهما لا ينتج أي منتج JS ، لذلك ربما لا يهم؟

92
Chris

interface هو عندما تريد ببساطة وصف شكل كائن. لا يوجد توليد للشفرات على الإطلاق للواجهات - إنها مجرد قطعة أثرية في نظام الكتابة. لن ترى أي اختلاف في إنشاء الشفرة لفئة ما بناءً على ما إذا كان يحتوي على جملة implements أم لا.

declare class هو عندما تريد وصف موجودة class (عادةً فئة TypeScript ، ولكن ليس دائمًا) ستكون موجودة من الخارج (على سبيل المثال ، لديك ملفان .ts يجمعان إلى ملفين .js و يتم تضمين كلاهما عبر علامات script في صفحة ويب). إذا كنت ترث من class باستخدام extends (بغض النظر عن ما إذا كان النوع الأساسي هو declare class أو class العادي) ، فسوف يقوم المحول البرمجي بإنشاء كل التعليمات البرمجية لتوصيل سلسلة النموذج الأولي وإعادة توجيه منشئي البيانات وما لا.

إذا حاولت أن ترث من declare class والتي كان من المفترض أن تكون واجهة ، فسوف يكون لديك خطأ في وقت التشغيل لأن هذا الرمز الذي تم إنشاؤه سوف يشير إلى كائن بدون أي مظهر وقت تشغيل.

على العكس من ذلك ، إذا كنت ببساطة implement واجهة يجب أن تكون declare class ، فسيتعين عليك إعادة تنفيذ جميع الأعضاء بنفسك ولن تستفيد من إعادة استخدام أي كود من الفئة الأساسية المحتملة ، والوظائف التي تتحقق من سلسلة النموذج الأولي في وقت التشغيل سوف ترفض الكائن الخاص بك لأنه لا يمثل في الواقع مثيلًا للفئة الأساسية.

للحصول على nerdy ، إذا كان لديك خلفية C++ ، فيمكنك التفكير في interface كـ typedef و declare class كإعلان extern لمُنشئ يفتقر تمامًا إلى تعريف في وحدة الترجمة هذه.

من جانب الاستهلاك الصافي (كتابة التعليمات البرمجية الضرورية ، وليس إضافة أنواع جديدة) ، الفرق الوحيد بين interface و declare class هو أنه لا يمكنك new واجهة. ومع ذلك ، إذا كنت تنوي extend/implement أحد هذه الأنواع في class جديد ، فلابد أنك اخترت بشكل صحيح بين interface و declare class. واحد منهم فقط سوف تعمل.

قاعدتان من شأنها أن تخدمك بشكل جيد:

  • هل اسم النوع محاذاة مع دالة منشئ (شيء غير معروف بـ new) موجود فعليًا في وقت التشغيل (على سبيل المثال ، Date موجود ، لكن JQueryStatic غير موجود)؟ إذا لا ، فأنت تريد بالتأكيد interface
  • هل أتعامل مع فئة مترجمة من ملف TypeScript آخر ، أو شيء مشابه بدرجة كافية؟ إذا نعم ، استخدم declare class
142
Ryan Cavanaugh

يمكنك تنفيذ الواجهة:

class MyClass implements Example {
    Method() {

    }
}

في حين أن بنية declare class تهدف فعلاً إلى استخدامها لإضافة تعريفات النوع للرمز الخارجي الذي لم تتم كتابته في TypeScript - وبالتالي فإن التنفيذ "في مكان آخر".

18
Fenton

في مصطلحات الشخص العادي ، يتم استخدام declare في ملفات .ts/d.ts لإعلام المترجم بأنه ينبغي لنا أن نتوقع وجود الكلمة الرئيسية declaring في تلك البيئة ، حتى لو لم يتم تعريفها في الملف الحالي. سيسمح لنا ذلك بعد ذلك بالحصول على أمان الكتابة عند استخدام الكائن المُعلَن ، حيث يعرف مترجم TypeScript الآن أن بعض المكونات الأخرى قد توفر هذا المتغير.

10
nikk wong

الفرق بين declare و interface في TS:

أعلن:

declare class Example {
    public Method(): void; 
}

في التعليمة البرمجية أعلاه declare ، يتيح برنامج التحويل البرمجي TS معرفة أنه في مكان ما يتم الإعلان عن الفئة Example. هذا لا يعني أن الفصل مدرج بطريقة سحرية. أنت كمبرمج تكون مسؤولاً عن إتاحة الفصل عندما تعلن ذلك (باستخدام declare الكلمة الأساسية).

جهة تعامل:

interface Example {
    Method(): void;
}

interface هي بنية افتراضية موجودة فقط داخل TypeScript. يستخدم برنامج التحويل البرمجي لـ TypeScript لغرض وحيد هو التحقق من النوع. عندما يتم ترجمة الكود إلى javascript ، سيتم تجريد هذه البنية بالكامل. يستخدم برنامج التحويل البرمجي لـ TypeScript واجهات للتحقق مما إذا كانت الكائنات لها البنية الصحيحة.

على سبيل المثال عندما يكون لدينا الواجهة التالية:

interface test {
  foo: number,
  bar: string,
}

تحتاج الكائنات التي نحددها والتي لها نوع الواجهة هذا إلى مطابقة الواجهة تمامًا:

// perfect match has all the properties with the right types, TS compiler will not complain.
  const obj1: test = {   
    foo: 5,
    bar: 'hey',
  }
3
Willem van der Veen