إضافة تعليقات توضيحية إلى جافا سكريبت لمنشئ صفحات الإغلاق

ملاحظة: هذه الصفحة قديمة. يتم الاحتفاظ بالقائمة الكاملة على https://github.com/google/closure-aggregater/wiki/Annotating-JavaScript-for-the-Closure-Compiler

نظرة عامة

يمكن لمجمِّع برامج Closure Compiler استخدام معلومات نوع البيانات حول متغيّرات JavaScript لتوفير تحسين وتحذيرات محسَّنة. ومع ذلك، لا تتوفّر في JavaScript طريقة للإعلان عن الأنواع.

يجب استخدام التعليقات في الرمز لتحديد نوع البيانات لأنّ JavaScript لا تتضمن أي بنية للإعلان عن نوع المتغيّر.

تُستمد لغة نوع Closure Compiler من التعليقات التوضيحية التي تستخدمها أداة إنشاء مستندات JSDoc، على الرغم من أنها قد انقسمت منذ ذلك الحين. وهو يتضمن الآن تعليقات توضيحية غير متوافقة مع JSDoc، والعكس صحيح. يوضّح هذا المستند مجموعة من التعليقات التوضيحية وتعبيرات النوع التي يفهمها منشئ محتوى "الإغلاق".

  1. علامات JSDoc
  2. تعبيرات النوع
  3. الأنواع العامة

علامات JSDoc

تبحث أداة Closure Compiler عن معلومات النوع في علامات JSDoc. استخدِم علامات JSDoc الموضّحة في الجدول المرجعي أدناه لمساعدة برنامج التجميع في تحسين الرمز والتحقّق من خلوّه من الأخطاء المحتملة وأخطاء أخرى.

يتضمّن هذا الجدول العلامات التي تؤثر في سلوك برنامج Closure Compiler فقط. للحصول على معلومات عن علامات JSDoc الأخرى، يمكنك الاطّلاع على مستندات مجموعة أدوات JSDoc.

العلامة الوصف
@abstract

لوضع علامة على طريقة باعتبارها مجردة. على غرار تعيين طريقة إلى goog.abstractMethod، يمكن للمجمِّع تقليم الطرق التي تمت إضافة تعليقات توضيحية إليها باستخدام @abstract لتقليل حجم الرمز.

يصدر المحول البرمجي تحذيرًا إذا كانت إحدى الطرق التي تم وضع علامة @abstract عليها تحتوي على تنفيذ غير فارغ.

على سبيل المثال:
/** @abstract */
foo.MyClass.prototype.abstractMethod = function() {};
@const

وضع علامة على متغير للقراءة فقط. يمكن للمحول البرمجي تضمين متغيرات @const، مما يحسّن شفرة جافا سكريبت.

تعريف النوع اختياري.

يصدر المُجمِّع تحذيرًا في حالة تعيين قيمة متغير أكثر من مرة واحدة لمتغير يحمل علامة @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

وضع علامة على دالة كدالة إنشاء. تتطلب المحول البرمجي تعليقات توضيحية @constructor لأي وظيفة يتم استخدامها مع الكلمة الرئيسية new

مثلاً:

/**
 * 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

يتم استخدام @dict لإنشاء كائنات بعدد متغير من الخصائص. عندما يتم وضع تعليق توضيحي على دالة إنشاء (Foo في المثال) باستخدام @dict، يمكنك استخدام علامة القوس فقط للوصول إلى خصائص كائنات Foo. كما يمكن استخدام التعليق التوضيحي مباشرةً على العناصر الحرفية للكائن.

مثلاً:

/**
 * @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 تعبير النوع.

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

مثلاً:

/**
 * Enum for tri-state values.
 * @enum {number}
 */
project.TriState = {
  TRUE: 1,
  FALSE: -1,
  MAYBE: 0
};
@export

وفقًا لهذا الرمز

/** @export */
foo.MyPublicClass.prototype.myPublicMethod = function() {
  // ...
};

عند تشغيل المحول البرمجي باستخدام العلامة --generate_exports، سينشئ الرمز:

goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod',
  foo.MyPublicClass.prototype.myPublicMethod);

والذي سيصدِّر الرموز إلى شفرة غير مجمّعة. يمكنك كتابة /** @export {SomeType} */ كاختصار لـ

/**
 * @export
 * @type {SomeType}
 */

يجب أن تكون الشفرة التي تستخدم تعليق @export التوضيحي إما

  1. تتضمن closure/base.js، أو
  2. يمكنك تحديد كل من goog.exportSymbol وgoog.exportProperty باستخدام توقيع الطريقة نفسه في قاعدة الرموز الخاصة بهما.
@extends

لتمييز فئة أو واجهة على أنها مكتسبة من صف آخر. يجب أيضًا وضع علامة على الفصل الدراسي الذي يحمل العلامة @extends إما @constructor أو @interface.

ملاحظة: لا يتسبب @extends في اكتساب فئة من صف آخر. ويخبر التعليق التوضيحي المحول البرمجي بأنه يمكنه التعامل مع فئة كفئة فرعية من فئة أخرى أثناء التحقق من النوع.

للاطّلاع على مثال حول تنفيذ الاكتساب، يُرجى الاطّلاع على وظيفة "مكتبة الإغلاق" goog.inherits().

مثلاً:

/**
 * 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

يتم استخدامها مع @constructor للإشارة إلى أن الصف يستخدم واجهة.

يصدر المحوّل البرمجي تحذيرًا إذا وضعت علامة على دالة إنشاء باستخدام @implements ثم تعذّر تنفيذ جميع الطرق والخصائص التي حددتها الواجهة.

مثلاً:


/**
 * A shape.
 * @interface
 */
function Shape() {};
Shape.prototype.draw = function() {};

/**
 * @constructor
 * @implements {Shape}
 */
function Square() {};
Square.prototype.draw = function() {
  ...
};
@implicitCast

ولا يمكن أن يظهر هذا التعليق التوضيحي إلا في إعلانات خصائص خارجية. يتضمن الموقع نوعًا معلنًا عنه، ولكن يمكنك تعيين أي نوع له بدون تحذير. وعند الدخول إلى الموقع، ستعود قيمة من النوع المعلن عنه. على سبيل المثال، يمكن تخصيص element.innerHTML لأي نوع، ولكن ستعرض دائمًا سلسلة.

/**
 * @type {string}
 * @implicitCast
 */
Element.prototype.innerHTML;
@inheritDoc

يشير إلى أن طريقة أو خاصية لفئة فرعية تخفي عمدًا طريقة أو خاصية من الفئة الفائقة، وتحتوي على الوثائق نفسها بالضبط. لاحظ أن علامة @inheritDoc تضمن العلامة @override.

مثلاً:

/** @inheritDoc */
project.SubClass.prototype.toString = function() {
  ...
};
@interface

لوضع علامة على دالة كواجهة. تحدد الواجهة الأعضاء المطلوبين من نوع ما. يجب أن تنفذ أي فئة تستخدم واجهة ما جميع الطرق والخصائص المحددة في النموذج الأولي للواجهة. راجع @implements.

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

مثلاً:

/**
 * A shape.
 * @interface
 */
function Shape() {};
Shape.prototype.draw = function() {};

/**
 * A polygon.
 * @interface
 * @extends {Shape}
 */
function Polygon() {};
Polygon.prototype.getSides = function() {};
@lends

تشير هذه القيمة إلى ضرورة التعامل مع مفاتيح الكائن بشكل حرفي على أنها خصائص لكائن آخر. يجب أن يظهر هذا التعليق التوضيحي على العناصر الحرفية للكائن فقط.

لاحظ أن الاسم الذي بين قوسين معقوفين ليس اسم نوع مثل التعليقات التوضيحية الأخرى. إنه اسم كائن. يحدد اسم الكائن الذي يتم إعارة الخصائص إليه. على سبيل المثال، يعني @type {Foo} "نسخة افتراضية من Foo"، ولكن @lends {Foo} تعني "المنشئ Foo".

تحتوي مستندات مجموعة أدوات 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

تشير هذه الخاصية إلى خاصية يجب عدم تصغيرها بواسطة المحوِّل البرمجي إلى متغير. الاستخدام الأساسي لـ @nocollapse هو السماح بتصدير المواقع القابلة للتغيير. تجدر الإشارة إلى أنه لا يزال من الممكن إعادة تسمية الخصائص غير المصغرة في برنامج التحويل البرمجي. في حالة التعليق التوضيحي على خاصية تمثل كائنًا مع @nocollapse، فإن جميع سماته ستظل أيضًا غير قابلة للتصغير.

مثلاً:

/**
 * A namespace.
 * @const
 */
var foo = {};

/**
 * @nocollapse
 */
foo.bar = 42;

window['foobar'] = foo.bar;
@nosideeffects

تشير إلى أن استدعاء الدالة الخارجية المعلنة ليس له أي آثار جانبية. يسمح هذا التعليق التوضيحي للمحول البرمجي بإزالة الاستدعاءات للدالة إذا لم يتم استخدام قيمة العرض. لا يُسمح بالتعليق التوضيحي إلا في extern files.

مثلاً:

/** @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

وضع علامة على عضو أو خاصية كحزمة خاصة. ولا يمكن إلا للرمز في الدليل نفسه الدخول إلى الأسماء التي تم وضع علامة @package عليها. وعلى وجه الخصوص، لا يمكن للرموز في الأدلة الرئيسية والأدلة الفرعية الوصول إلى الأسماء التي تم وضع علامة @package عليها.

يمكن أن تتضمن دالة الإنشاء العامة خصائص @package لتقييد الطرق التي يمكن للمتصلين خارج الدليل استخدامها. من ناحية أخرى، يمكن أن تحتوي دالة الإنشاء على @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

يتم استخدامه مع تعريفات الطريقة والدالة والمُنشئ لتحديد أنواع وسيطات الدوال. يجب أن تكون علامات @param بنفس ترتيب المعلمات في تعريف الدالة.

يجب أن تتبع العلامة @param تعبير نوع.

بدلاً من ذلك، يمكنك وضع تعليقات توضيحية على أنواع المعلمات المضمنة (راجع الدالة foo في المثال).

مثلاً:


/**
 * 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

وضع علامة على العضو كخاص. ولا يمكن إلا للرمز في الملف نفسه الوصول إلى المتغيرات والوظائف العامة المميّزة بعلامة @private. لا يمكن إنشاء مثيل للإنشاءات التي تم وضع علامة @private عليها إلا من خلال رمز في الملف نفسه ومن خلال أعضائها الثابتة وأعضاء النسخة الافتراضية.

يمكن أيضًا الوصول إلى الخصائص الثابتة العامة للإنشاءات التي تم وضع علامة @private عليها في أي مكان، ويمكن لعامل التشغيل instanceof الوصول دائمًا إلى أعضاء @private.

مثلاً:

/**
 * Handlers that are listening to this logger.
 * @private {Array<Function>}
 */
this.handlers_ = [];

@protected

يشير إلى أن العضو أو الموقع محمي.

يمكن للموقع الذي يحمل علامة @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

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

مثلاً:

/**
 * 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

تحدّد هذه السمة أنواع تعريفات الطريقة والدوال. يجب أن تتبع العلامة @return تعبير نوع.

بدلاً من ذلك، يمكنك إضافة تعليقات توضيحية إلى نوع الإرجاع مضمّن (راجع الدالة foo في المثال).

إذا كانت إحدى الدوال غير الموجودة في القيم الخارجية ليس لها قيمة عرض، يمكنك حذف العلامة @return، وسيفترض المُجمِّع أن الدالة تعرض undefined.

مثلاً:

/**
 * 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

يتم استخدام @struct لإنشاء كائنات بعدد ثابت من الخصائص. عندما يتم وضع تعليق توضيحي على دالة إنشاء (Foo في المثال) باستخدام @struct، يمكنك فقط استخدام علامة النقطة للوصول إلى خصائص كائنات Foo، وليس تدوين القوس. ولا يمكنك أيضًا إضافة موقع إلكتروني إلى مثيل Foo بعد إنشائه. كما يمكن استخدام التعليق التوضيحي مباشرةً على العناصر الحرفية للكائن.

مثلاً:

/**
 * @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

تحدّد نوع الكائن الذي تشير إليه الكلمة الرئيسية this ضمن دالة. يجب أن تتبع العلامة @this تعبير نوع.

لمنع تحذيرات المُحول البرمجي، يجب استخدام تعليق توضيحي لـ @this كلما ظهر this في دالة ليست طريقة أولية أو دالة مميزة بعلامة @constructor.

مثلاً:

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

تحدد نوع المتغير أو الخاصية أو التعبير. يجب أن تتبع العلامة @type تعبير نوع.

عند الإعلان عن متغيّر أو معلّمة دالة، يمكنك كتابة التعليق التوضيحي المضمّن مع حذف {} و@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

للإشارة إلى أن الفئة ليست من النوع @struct، أو النوع @dict. وهذه هي القيمة التلقائية، لذا ليس من الضروري بشكل عام كتابتها بشكلٍ صريح، إلا إذا كنت تستخدم goog.defineClass، أو الكلمة الرئيسية التي تستخدم class، وكلاهما ينتجان فئات تبلغ @struct تلقائيًا.

مثلاً:

/**
 * @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>}
مصفوفة من السلاسل.

{Object<string, number>}
كائن تكون فيه المفاتيح سلاسل وتمثل القيم أرقامًا.

لترميز نوع مع مجموعة من وسيطات النوع. مثل البرامج العامة لجافا.
النوع يونيون {(number|boolean)}
رقم أو قيمة منطقية

عليك وضع علامة على الأقواس المطلوبة.
يشير إلى أن القيمة قد تكون من النوع A أو النوع B.
نوع السجل {{myNum: number, myObject}}
نوع مجهول يحمل اسمًا باسم myNum يحمل قيمة من النوع number وخاصية بالاسم myObject وتكون له أي نوع.

يشير إلى أن القيمة تتضمن الأعضاء المحددين بقيم الأنواع المحددة.

الأقواس هي جزء من بنية النوع. على سبيل المثال، للإشارة إلى Array من العناصر التي تحتوي على خاصية length، يمكنك كتابة:
Array<{length}>. في المثال على اليسار، توضح الأقواس الخارجية أن هذا هو نوع التعبير والأقواس الداخلية تشير إلى أن هذا هو نوع السجل.

نوع قابل للإلغاء {?number}
رقم أو null.

يشير إلى أن القيمة من النوع A أو null.

وتكون جميع أنواع الكائنات خالية من القيم الافتراضية بشكل تلقائي سواء تم تعريفها بواسطة عامل التشغيل 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.

إلى أن الوسيطة التي تم وصفها بواسطة تعليق توضيحي لـ @param اختيارية. يمكن أن يؤدي استدعاء الدالة إلى حذف وسيطة اختيارية. لا يمكن أن تسبق المعلمة الاختيارية معلمة غير اختيارية في قائمة المعلمات.

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

/**
 * 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