ملاحظة: هذه الصفحة قديمة. يتم الاحتفاظ بالقائمة الكاملة على https://github.com/google/closure-aggregater/wiki/Annotating-JavaScript-for-the-Closure-Compiler
نظرة عامة
يمكن لمجمِّع برامج Closure Compiler استخدام معلومات نوع البيانات حول متغيّرات JavaScript لتوفير تحسين وتحذيرات محسَّنة. ومع ذلك، لا تتوفّر في JavaScript طريقة للإعلان عن الأنواع.
يجب استخدام التعليقات في الرمز لتحديد نوع البيانات لأنّ JavaScript لا تتضمن أي بنية للإعلان عن نوع المتغيّر.
تُستمد لغة نوع Closure Compiler من التعليقات التوضيحية التي تستخدمها أداة إنشاء مستندات JSDoc، على الرغم من أنها قد انقسمت منذ ذلك الحين. وهو يتضمن الآن تعليقات توضيحية غير متوافقة مع JSDoc، والعكس صحيح. يوضّح هذا المستند مجموعة من التعليقات التوضيحية وتعبيرات النوع التي يفهمها منشئ محتوى "الإغلاق".
علامات JSDoc
تبحث أداة Closure Compiler عن معلومات النوع في علامات JSDoc. استخدِم علامات JSDoc الموضّحة في الجدول المرجعي أدناه لمساعدة برنامج التجميع في تحسين الرمز والتحقّق من خلوّه من الأخطاء المحتملة وأخطاء أخرى.
يتضمّن هذا الجدول العلامات التي تؤثر في سلوك برنامج Closure Compiler فقط. للحصول على معلومات عن علامات JSDoc الأخرى، يمكنك الاطّلاع على مستندات مجموعة أدوات JSDoc.
العلامة | الوصف |
---|---|
@abstract
|
لوضع علامة على طريقة باعتبارها مجردة. على غرار تعيين طريقة إلى
يصدر المحول البرمجي تحذيرًا إذا كانت إحدى الطرق التي تم وضع علامة /** @abstract */ foo.MyClass.prototype.abstractMethod = function() {}; |
@const
|
وضع علامة على متغير للقراءة فقط. يمكن للمحول البرمجي تضمين متغيرات تعريف النوع اختياري.
يصدر المُجمِّع تحذيرًا في حالة تعيين قيمة متغير أكثر من مرة واحدة لمتغير يحمل علامة /** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; |
@constructor
|
وضع علامة على دالة كدالة إنشاء.
تتطلب المحول البرمجي تعليقات توضيحية مثلاً: /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
تشير هذه القيمة إلى ثابت يمكن أن تلغيه أداة التجميع في وقت التجميع.
باستخدام المثال على اليمين، يمكنك تمرير العلامة --define='ENABLE_DEBUG=false' إلى المحول البرمجي لتغيير قيمة ENABLE_DEBUG إلى false.
يمكن أن يكون نوع الثابت المحدد رقمًا أو سلسلة أو قيمة منطقية.
غير مسموح بالتعريفات إلا في النطاق العام.
مثلاً: /** @define {boolean} */ var ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; |
@deprecated
|
وضع علامة على دالة أو طريقة أو خاصية بحيث يؤدي استخدامها إلى عرض تحذير من برنامج التجميع يشير إلى وجوب عدم استخدامها بعد الآن. مثلاً: /** * Determines whether a node is a field. * @return {boolean} True if the contents of * the element are editable, but the element * itself is not. * @deprecated Use isField(). */ BN_EditUtil.isTopEditableField = function(node) { ... }; |
@dict
|
يتم استخدام مثلاً: /** * @constructor * @dict */ function Foo() {} var obj1 = new Foo(); obj1['x'] = 123; obj1.x = 234; // warning var obj2 = /** @dict */ { 'x': 321 }; obj2.x = 123; // warning |
@enum
|
تحدد هذه الخاصية نوع التعداد. التعداد هو كائن تتكون خصائصه
من مجموعة من الثوابت ذات الصلة. يجب أن تتبع العلامة ينطبق تصنيف النوع للإحصاء على كل خاصية من التعداد. على سبيل المثال، إذا كان أحد التعداد من النوع مثلاً: /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; |
@export
|
وفقًا لهذا الرمز /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
عند تشغيل المحول البرمجي باستخدام العلامة goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); والذي سيصدِّر الرموز إلى شفرة غير مجمّعة. يمكنك كتابة
/** * @export * @type {SomeType} */ يجب أن تكون الشفرة التي تستخدم تعليق
|
@extends
|
لتمييز فئة أو واجهة على أنها مكتسبة من صف آخر. يجب أيضًا وضع علامة على
الفصل الدراسي الذي يحمل العلامة
ملاحظة: لا يتسبب
للاطّلاع على مثال حول تنفيذ الاكتساب، يُرجى الاطّلاع على
وظيفة "مكتبة الإغلاق" مثلاً: /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
تشير إلى أن هذا الصف غير مسموح بتمديده. بالنسبة إلى الطرق، تشير إلى عدم السماح لأي فئة فرعية بتجاوز تلك الطريقة. مثلاً: /** * A class that cannot be extended. * @final * @constructor */ sloth.MyFinalClass = function() { ... } /** * A method that cannot be overridden. * @final */ sloth.MyFinalClass.prototype.method = function() { ... }; |
@implements
|
يتم استخدامها مع
يصدر المحوّل البرمجي تحذيرًا إذا وضعت علامة على دالة إنشاء باستخدام مثلاً: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; |
@implicitCast
|
ولا يمكن أن يظهر هذا التعليق التوضيحي إلا في إعلانات خصائص خارجية.
يتضمن الموقع نوعًا معلنًا عنه، ولكن يمكنك تعيين أي نوع له بدون تحذير. وعند الدخول إلى الموقع، ستعود قيمة
من النوع المعلن عنه. على سبيل المثال،
يمكن تخصيص /** * @type {string} * @implicitCast */ Element.prototype.innerHTML; |
@inheritDoc
|
يشير إلى أن طريقة أو خاصية لفئة فرعية
تخفي عمدًا طريقة أو خاصية من الفئة الفائقة، وتحتوي على الوثائق نفسها بالضبط. لاحظ أن علامة مثلاً: /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
لوضع علامة على دالة كواجهة. تحدد الواجهة الأعضاء المطلوبين من نوع ما. يجب أن تنفذ أي فئة تستخدم واجهة ما جميع الطرق والخصائص المحددة في النموذج الأولي للواجهة. راجع
تتحقق أداة التجميع من عدم إنشاء مثيلات للواجهات. إذا تم استخدام الكلمة الرئيسية مثلاً: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; |
@lends
|
تشير هذه القيمة إلى ضرورة التعامل مع مفاتيح الكائن بشكل حرفي على أنها خصائص لكائن آخر. يجب أن يظهر هذا التعليق التوضيحي على العناصر الحرفية للكائن فقط.
لاحظ أن الاسم الذي بين قوسين معقوفين ليس اسم نوع مثل
التعليقات التوضيحية الأخرى. إنه اسم كائن. يحدد
اسم الكائن الذي يتم إعارة الخصائص إليه.
على سبيل المثال، يعني تحتوي مستندات مجموعة أدوات JSDoc على مزيد من المعلومات حول هذا التعليق التوضيحي. مثلاً: goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license أو @preserve
|
المحول البرمجي يُطلب منه إدراج التعليق المرتبط قبل الرمز المُجمّع للملف المميّز بعلامة. يسمح هذا التعليق التوضيحي بالإشعارات المهمّة (مثل التراخيص القانونية أو نص حقوق الطبع والنشر) للحفاظ على تجميع البيانات بدون تغيير. يتم الحفاظ على فواصل الأسطر. مثلاً: /** * @preserve Copyright 2009 SomeThirdParty. * Here is the full license text and copyright * notice for this file. Note that the notice can span several * lines and is only terminated by the closing star and slash: */ |
@nocollapse
|
تشير هذه الخاصية إلى خاصية يجب عدم تصغيرها بواسطة المحوِّل البرمجي إلى متغير. الاستخدام الأساسي لـ مثلاً: /** * A namespace. * @const */ var foo = {}; /** * @nocollapse */ foo.bar = 42; window['foobar'] = foo.bar; |
@nosideeffects
|
تشير إلى أن استدعاء الدالة الخارجية المعلنة ليس له أي آثار جانبية.
يسمح هذا التعليق التوضيحي للمحول البرمجي بإزالة الاستدعاءات للدالة
إذا لم يتم استخدام قيمة العرض. لا يُسمح بالتعليق التوضيحي إلا في
مثلاً: /** @nosideeffects */ function noSideEffectsFn1() {} /** @nosideeffects */ var noSideEffectsFn2 = function() {}; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() {}; |
@override
|
يشير إلى أن طريقة أو خاصية للفئة الفرعية تخفي عمدًا طريقة أو خاصية للفئة الفرعية. إذا لم يتم تضمين أي تعليقات توضيحية أخرى، فإن الموقع أو الموقع سيكتسب التعليقات التوضيحية تلقائيًا من فئته المميزة. مثلاً: /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
وضع علامة على عضو أو خاصية كحزمة خاصة. ولا يمكن إلا للرمز في الدليل نفسه
الدخول إلى الأسماء التي تم وضع علامة
يمكن أن تتضمن دالة الإنشاء العامة خصائص مثلاً: /** * Returns the window object the foreign document resides in. * * @return {Object} The window object of the peer. * @package */ goog.net.xpc.CrossPageChannel.prototype.getPeerWindowObject = function() { // ... }; |
@param
|
يتم استخدامه مع تعريفات الطريقة والدالة والمُنشئ لتحديد أنواع وسيطات الدوال. يجب أن تكون علامات
يجب أن تتبع العلامة
بدلاً من ذلك، يمكنك وضع تعليقات توضيحية على أنواع المعلمات المضمنة
(راجع الدالة مثلاً: /** * Queries a Baz for items. * @param {number} groupNum Subgroup id to query. * @param {string|number|null} term An itemName, * or itemId, or null to search everything. */ goog.Baz.prototype.query = function(groupNum, term) { ... }; function foo(/** number */ a, /** number */ b) { return a - b + 1; }بالنسبة إلى المعلّمات التي تمثل نمطًا للتدمير، يمكنك استخدام أي اسم يمثّل معرّف JavaScript صالحًا، بعد التعليق التوضيحي للنوع. /** * @param {{name: string, age: number}} person */ function logPerson({name, age}) { console.log(`${name} is ${age} years old`); } |
@private
|
وضع علامة على العضو كخاص. ولا يمكن إلا للرمز في الملف نفسه الوصول إلى المتغيرات والوظائف العامة المميّزة بعلامة
يمكن أيضًا الوصول إلى الخصائص الثابتة العامة للإنشاءات
التي تم وضع علامة مثلاً: /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
يشير إلى أن العضو أو الموقع محمي.
يمكن للموقع الذي يحمل علامة
مثلاً: /** * Sets the component's root element to the given element. * Considered protected and final. * @param {Element} element Root element for the component. * @protected */ goog.ui.Component.prototype.setElementInternal = function(element) { // ... }; |
@record
|
لوضع علامة على إحدى الوظائف كواجهة إنشائية. تشبه الواجهة البنيوية واجهة مثلاً: /** * Anything with a draw() method. * @record */ function Drawable() {}; Drawable.prototype.draw = function() {}; /** * A polygon. * @param {!Drawable} x */ function render(x) { x.draw(); }; var o = { draw() { /* ... */ } }; render(o); |
@return
|
تحدّد هذه السمة أنواع تعريفات الطريقة والدوال.
يجب أن تتبع العلامة
بدلاً من ذلك، يمكنك إضافة تعليقات توضيحية إلى نوع الإرجاع مضمّن
(راجع الدالة
إذا كانت إحدى الدوال غير الموجودة في القيم الخارجية ليس لها قيمة عرض، يمكنك حذف العلامة مثلاً: /** * Returns the ID of the last item. * @return {string} The hex ID. */ goog.Baz.prototype.getLastId = function() { ... return id; }; function /** number */ foo(x) { return x - 1; } |
@struct
|
يتم استخدام مثلاً: /** * @constructor * @struct */ function Foo(x) { this.x = x; } var obj1 = new Foo(123); var someVar = obj1.x; // OK obj1.x = "qwerty"; // OK obj1['x'] = "asdf"; // warning obj1.y = 5; // warning var obj2 = /** @struct */ { x: 321 }; obj2['x'] = 123; // warning |
@template
|
راجع الأنواع العامة. مثلاً: /** * @param {T} t * @constructor * @template T */ Container = function(t) { ... }; |
@this
|
تحدّد نوع الكائن الذي تشير إليه الكلمة الرئيسية
لمنع تحذيرات المُحول البرمجي، يجب استخدام تعليق توضيحي لـ مثلاً: chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this {Widget} * @return {Element} */ function() { return this.getComponent().getElement(); }); |
@throws
|
تُستخدم لتوثيق الاستثناءات المفروضة بواسطة دالة. لا يستخدم مدقق النوع هذه المعلومات في الوقت الحالي. ويتم استخدامها فقط لمعرفة ما إذا كانت إحدى الدوال المُعلَنة في ملف خارجي لها آثار جانبية. مثلاً: /** * @throws {DOMException} */ DOMApplicationCache.prototype.swapCache = function() { ... }; |
@type
|
تحدد نوع المتغير أو الخاصية أو التعبير. يجب أن تتبع العلامة عند الإعلان عن متغيّر أو معلّمة دالة، يمكنك كتابة التعليق التوضيحي المضمّن مع حذف مثلاً: /** * The message hex ID. * @type {string} */ var hexId = hexId; var /** string */ name = 'Jamie'; function useSomething(/** (string|number|!Object) */ something) { ... } |
@typedef
|
للإعلان عن اسم مستعار لنوع أكثر تعقيدًا. في الوقت الحالي، لا يمكن تحديد أنواع المتغيّرات إلا على المستوى العلوي، وليس داخل الدوال. وقد أصلحنا هذا القيد في استنتاج النوع الجديد. مثلاً: /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } |
@unrestricted
|
للإشارة إلى أن الفئة ليست من النوع مثلاً: /** * @constructor * @unrestricted */ function Foo(x) { this.x = x; } var obj1 = new Foo(123); var someVar = obj1.x; // OK obj1.x = "qwerty"; // OK obj1['x'] = "asdf"; // OK obj1.y = 5; // OK |
تعبيرات النوع
يمكنك تحديد نوع البيانات لأي متغير أو خاصية أو تعبير أو معلمة دالة باستخدام تعبير النوع. يتكون التعبير النوع من الأقواس المعقوفة ("{ }") التي تحتوي على مزيج من عوامل تشغيل الأنواع الموضحة أدناه.
استخدِم تعبير النوع مع العلامة @param
للإشارة إلى نوع معلمة الدالة. استخدِم تعبير النوع مع العلامة @type
للإشارة إلى نوع المتغيّر أو الخاصية أو التعبير.
كلما ازداد عدد الأنواع التي تحدّدها في الرمز، ازداد عدد عمليات التحسين التي يمكن أن يجريها برنامج التجميع وزاد عدد الأخطاء التي يمكن أن يرصدها.
يستخدم المحول البرمجي هذه التعليقات التوضيحية للتحقق من نوع برنامجك.
يُرجى العِلم بأنّ برنامج Closure Compiler لا يقدّم أي تعهدات بأنه
سيتمكّن من معرفة نوع كل تعبير في
برنامجك. ويبذل الموقع الإلكتروني أفضل جهد ممكن من خلال الاطّلاع على كيفية استخدام المتغيّرات ونوع التعليقات التوضيحية المرتبطة بإعلاناته. ثم يستخدم عددًا من خوارزميات استنتاج النوع لمعرفة نوع أكبر عدد ممكن من التعبيرات. بعض هذه الخوارزميات سهلة الاستخدام ("إذا كان س رقمًا، ونرى
y = x;
، يكون ص رقمًا). وتكون بعض القيم أكثر غير مباشرة ("إذا تم توثيق المعلمة f الأولى كاستدعاء يجب أن يأخذ رقمًا، ورأينا f(function(x) { /** ... */ });
، إذًا يجب أن تكون x رقمًا").
اسم المشغّل | أمثلة على البنية | الوصف |
---|---|---|
اكتب الاسم |
{boolean} {Window} {goog.ui.Menu}
|
لتحديد اسم أحد الأنواع. |
نوع التطبيق |
{Array<string>} مصفوفة من السلاسل.
|
لترميز نوع مع مجموعة من وسيطات النوع. مثل البرامج العامة لجافا. |
النوع يونيون |
{(number|boolean)} رقم أو قيمة منطقية عليك وضع علامة على الأقواس المطلوبة. |
يشير إلى أن القيمة قد تكون من النوع A أو النوع B. |
نوع السجل |
{{myNum: number, myObject}}
نوع مجهول يحمل اسمًا باسم myNum يحمل قيمة من النوع number وخاصية بالاسم myObject وتكون له أي نوع.
|
يشير إلى أن القيمة تتضمن الأعضاء المحددين بقيم الأنواع المحددة. الأقواس هي جزء من بنية النوع. على سبيل المثال، للإشارة إلى |
نوع قابل للإلغاء |
{?number} رقم أو null .
|
يشير إلى أن القيمة من النوع A أو وتكون جميع أنواع الكائنات خالية من القيم الافتراضية بشكل تلقائي سواء تم تعريفها بواسطة عامل التشغيل Nullable أم لا. يتم تعريف نوع الكائن على أنه أي شيء باستثناء دالة أو سلسلة أو رقم أو قيمة منطقية. ولجعل نوع الكائن غير قابل للإفراغ، استخدِم عامل التشغيل Non-nullable. |
نوع غير قابل للقيم الفارغة |
{!Object} كائن، ولكن ليس قيمة null مطلقًا.
|
يشير إلى أن القيمة من النوع A وليست فارغة. الدوال وجميع أنواع القيم (القيمة المنطقية والرقم والسلسلة) غير قابلة للإبطال بشكلٍ تلقائي سواء تم الإعلان عنها من خلال عامل التشغيل غير قابل للقيم الفارغة. ولجعل القيمة أو نوع الدالة خاليًا، استخدم عامل التشغيل Nullable. |
نوع الدالة |
{function(string, boolean)} دالة تأخذ معلمتين (سلسلة وقيمة منطقية)، وتحتوي على قيمة عرض غير معروفة. |
تحدد دالة وأنواع معلمات الدالة. |
نوع عرض الدالة |
{function(): number} دالة لا تستخدم مَعلمات وتعرض رقمًا. |
تحدد هذه السمة نوع القيمة التي تعرضها دالة. |
نوع الدالة this |
{function(this:goog.ui.Menu, string)} دالة تأخذ معلمة واحدة (سلسلة)، ويتم تنفيذها في سياق goog.ui.Menu. |
تحدد نوع قيمة this داخل الدالة. |
نوع الدالة new |
{function(new:goog.ui.Menu, string)} دالة تأخذ معلمة واحدة (سلسلة)، وتنشئ مثيلاً جديدًا من goog.ui.Menu عند طلبها باستخدام الكلمة الرئيسية "الجديدة". |
تحدّد هذه الخاصية نوع الإنشاء. |
المعلّمات المتغيرة |
{function(string, ...number): number} دالة تأخذ معلمة واحدة (سلسلة)، ثم عددًا متغيرًا من المعلمات التي يجب أن تكون أرقامًا. |
تشير إلى أن نوع الدالة يأخذ عددًا متغيرًا من المعلمات، ويحدد نوعًا لمعلمات المتغير. |
المعلّمات المتغيرة (في تعليقين توضيحيين (@param ))
|
@param {...number} var_args عدد متغير من المعلمات لدالة تعليقات توضيحية. |
تشير إلى أن الدالة التي تتضمن تعليقًا توضيحيًا تقبل عددًا متغيرًا من المعلمات، وتحدّد نوعًا للمعلمات المتغيرة. |
معلمة اختيارية في تعليق توضيحي لـ @param
|
@param {number=} opt_argument معلمة اختيارية من النوع number .
|
إلى أن الوسيطة التي تم وصفها بواسطة
تعليق توضيحي لـ
إذا أغفل استدعاء الطريقة معلمة اختيارية، ستحتوي هذه الوسيطة على القيمة /** * Some class, initialized with an optional value. * @param {Object=} opt_value Some value (optional). * @constructor */ function MyClass(opt_value) { /** * Some value. * @type {Object|undefined} */ this.myValue = opt_value; } |
وسيطة اختيارية في نوع الدالة |
{function(?string=, number=)} دالة تأخذ سلسلة اختيارية واحدة فارغة ويمكن اختيار رقم واحد اختياري كوسيطات. |
تشير إلى أن الوسيطة في نوع الدالة اختيارية. يمكن حذف وسيطة اختيارية من استدعاء الدالة. لا يمكن أن تسبق الوسيطة الاختيارية وسيطة غير اختيارية في قائمة الوسيطات. |
النوع "الكل" | {*} |
تشير إلى أن المتغير يمكن أن يأخذ أي نوع. |
النوع غير معروف | {?} |
يشير إلى أن المتغيّر يمكن أن يأخذ أي نوع من المحول البرمجي، ويجب ألا يفحص المحوِّل البرمجي أي استخدامات له. |
نوع الإرسال
لإرسال قيمة إلى نوع معين، استخدم هذه البنية
/** @type {!MyType} */ (valueExpression)يجب دائمًا وضع الأقواس حول التعبير.
الأنواع العامة
وتمامًا مثل جافا، تدعم "أداة إغلاق التصفّح" الأنواع والوظائف والطرق العامة. تعمل العناصر العامة على كائنات من أنواع مختلفة مع الحفاظ على أمان نوع وقت التجميع.
يمكنك استخدام عناصر عامة لتنفيذ مجموعات عامة تتضمّن إشارات إلى كائنات من نوع معيّن وخوارزميات عامة تعمل على كائنات من نوع معيّن.
الإعلان عن نوع عام
يمكن جعل النوع عامًا من خلال إضافة تعليق توضيحي @template
إلى دالة إنشاء النوع (للصفوف) أو بيان الواجهة (للواجهات). مثلاً:
/** * @constructor * @template T */ Foo = function() { ... };
ويشير التعليق التوضيحي @template T
إلى أن Foo
هو نوع عام بنوع واحد من النماذج، وهو T
.
يمكن استخدام نوع النموذج T
كنوع ضمن نطاق تعريف Foo
. مثلاً:
/** @return {T} */ Foo.prototype.get = function() { ... }; /** @param {T} t */ Foo.prototype.set = function(t) { ... };
ستعرض الطريقة get
كائنًا من النوع T
،
والطريقة set
لن تقبل سوى الكائنات من النوع T
.
إنشاء مثيل عام لنوع
عند إعادة استخدام المثال أعلاه، يمكن إنشاء نسخة افتراضية من النموذج Foo
بعدة طرق:
/** @type {!Foo<string>} */ var foo = new Foo(); var foo = /** @type {!Foo<string>} */ (new Foo());
كلتا العبارتين دالة الإنشاء أعلاه تنشئ مثيل Foo
ونوع النموذج T
هو string
. ستفرض أداة التجميع
الاستدعاءات لطرق foo
والوصول إلى خصائص foo
، مع مراعاة نوع النموذج. مثلاً:
foo.set("hello"); // OK. foo.set(3); // Error - expected a string, found a number. var x = foo.get(); // x is a string.
يمكن أيضًا كتابة المثيلات ضمنيًا من خلال وسيطات دالة الإنشاء.
ننصحك باستخدام نوع عام مختلف، Bar
:
/** * @param {T} t * @constructor * @template T */ Bar = function(t) { ... }; var bar = new Bar("hello"); // bar is a Bar<string>
يتم استنتاج نوع الوسيطة للمُنشئ Bar
على أنه string
، ونتيجة لذلك، يتم استنتاج المثيل الذي تم إنشاؤه bar
على أنه Bar<string>
.
أنواع النماذج المتعددة
يمكن أن تحتوي العلامة العامة على أي عدد من أنواع النماذج. تحتوي فئة الخريطة التالية على نوعين من النماذج:
/** * @constructor * @template Key, Val */ MyMap = function() { ... };
يجب تحديد كل أنواع النماذج لنوع عام في التعليق التوضيحي
@template
نفسه، كقائمة مفصولة بفواصل. ويعتبر ترتيب أسماء أنواع النماذج أمرًا مهمًا، نظرًا لأن التعليقات التوضيحية لنوع النموذج ستستخدم الترتيب لإقران أنواع النماذج مع القيم. مثلاً:
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
الثبات من الأنواع العامة
يفرض تطبيق Closure Compiler الكتابة العامة غير الثابتة. وهذا يعني أنه إذا توقع السياق من النوع Foo<X>
، لا يمكنك تمرير النوع Foo<Y>
إذا كانت X
وY
نوعين مختلفين، حتى إذا كان أحدهما نوعًا فرعيًا للنوع الآخر. مثلاً:
/** * @constructor */ X = function() { ... }; /** * @extends {X} * @constructor */ Y = function() { ... }; /** @type {Foo<X>} */ var fooX; /** @type {Foo<Y>} */ var fooY; fooX = fooY; // Error fooY = fooX; // Error /** @param {Foo<Y>} fooY */ takesFooY = function(fooY) { ... }; takesFooY(fooY); // OK. takesFooY(fooX); // Error
اكتساب أنواع عامة
ويمكن اكتساب الأنواع العامة، كما يمكن إصلاح أنواع النماذج أو نشرها على نوع الاكتساب. في ما يلي مثال لنوع موروث يعمل على إصلاح نوع النموذج من النوع الفائق:
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
من خلال تمديد A<string>
، سيكون لـ B
طريقة
method
تستخدم معلمة من النوع string
.
في ما يلي مثال لنوع موروث ينشر نوع النموذج من النوع الفائق:
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
من خلال تمديد A<U>
، ستحتوي المثيلات المستندة إلى نموذج من C
على الطريقة method
التي تستخدم معلمة من نوع النموذج U
.
يمكن تنفيذ الواجهات وتوسيعها بطريقة مشابهة، إلا أنه لا يمكن لنوع واحد تنفيذ الواجهة نفسها مرات عديدة بأنواع مختلفة من النماذج. مثلاً:
/** * @interface * @template T */ Foo = function() {}; /** @return {T} */ Foo.prototype.get = function() {}; /** * @constructor * @implements {Foo<string>} * @implements {Foo<number>} */ FooImpl = function() { ... }; // Error - implements the same interface twice
الدوال والطرق العامة
وعلى غرار الأنواع العامة، يمكن جعل الوظائف والأساليب عامة، وذلك بإضافة
تعليق توضيحي @template
إلى تعريفها. مثلاً:
/** * @param {T} a * @return {T} * @template T */ identity = function(a) { return a; }; /** @type {string} */ var msg = identity("hello") + identity("world"); // OK /** @type {number} */ var sum = identity(2) + identity(2); // OK /** @type {number} */ var sum = identity(2) + identity("2"); // Type mismatch