Closure Compiler के लिए JavaScript की जानकारी देना

ध्यान दें: यह पेज पुराना हो चुका है. पूरी सूची यहां दी गई है: https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler

खास जानकारी

Closure Compiler, JavaScript वैरिएबल के डेटा टाइप की जानकारी का इस्तेमाल कर सकता है. इससे बेहतर ऑप्टिमाइज़ेशन और चेतावनियां मिल सकती हैं. JavaScript में, टाइप तय करने का कोई तरीका नहीं है.

JavaScript में किसी वैरिएबल के टाइप का एलान करने के लिए कोई सिंटैक्स नहीं होता. इसलिए, आपको कोड में टिप्पणियों का इस्तेमाल करके डेटा टाइप के बारे में बताना होगा.

Closure Compiler की टाइप लैंग्वेज, JSDoc दस्तावेज़ जनरेट करने वाले टूल के इस्तेमाल किए गए एनोटेशन से ली गई है. हालांकि, अब यह अलग हो गई है. अब इसमें कई ऐसे एनोटेशन शामिल हैं जिन्हें JSDoc इस्तेमाल नहीं करता. इसके उलट, JSDoc में ऐसे कई एनोटेशन शामिल हैं जिन्हें यह इस्तेमाल नहीं करता. इस दस्तावेज़ में, एनोटेशन और टाइप एक्सप्रेशन के उस सेट के बारे में बताया गया है जिसे Closure Compiler समझता है.

  1. JSDoc टैग
  2. टाइप एक्सप्रेशन
  3. जेनेरिक टाइप

JSDoc टैग

Closure Compiler, JSDoc टैग में टाइप की जानकारी ढूंढता है. नीचे दी गई रेफ़रंस टेबल में बताए गए JSDoc टैग का इस्तेमाल करें. इससे कंपाइलर को आपके कोड को ऑप्टिमाइज़ करने में मदद मिलेगी. साथ ही, वह टाइप से जुड़ी संभावित गड़बड़ियों और अन्य गलतियों की जांच कर पाएगा.

इस टेबल में सिर्फ़ ऐसे टैग शामिल हैं जो Closure Compiler के व्यवहार पर असर डालते हैं. अन्य JSDoc टैग के बारे में जानकारी के लिए, JSDoc Toolkit का दस्तावेज़ देखें.

टैग ब्यौरा
@abstract

किसी तरीके को ऐब्स्ट्रैक्ट के तौर पर मार्क करता है. goog.abstractMethod के तौर पर किसी तरीके को सेट करने के तरीके की तरह ही, कंपाइलर @abstract के साथ एनोटेट किए गए तरीकों को हटा सकता है, ताकि कोड का साइज़ कम किया जा सके.

अगर @abstract के तौर पर मार्क की गई किसी तरीके का लागू करने का तरीका खाली नहीं है, तो कंपाइलर एक चेतावनी देता है.

उदाहरण के लिए:
/** @abstract */
foo.MyClass.prototype.abstractMethod = function() {};
@const

इस विकल्प का इस्तेमाल करके, किसी वैरिएबल को सिर्फ़ पढ़ने के लिए सेट किया जाता है. कंपाइलर, @const वैरिएबल को इनलाइन कर सकता है. इससे JavaScript कोड को ऑप्टिमाइज़ किया जा सकता है.

टाइप का एलान करना ज़रूरी नहीं है.

अगर @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

किसी फ़ंक्शन को कंस्ट्रक्टर के तौर पर मार्क करता है. कंपाइलर को new कीवर्ड के साथ इस्तेमाल किए जाने वाले किसी भी फ़ंक्शन के लिए, @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

@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 का टाइप तय करता है. एनम एक ऐसा ऑब्जेक्ट होता है जिसकी प्रॉपर्टी, मिलते-जुलते कॉन्स्टेंट का एक सेट बनाती हैं. @enum टैग के बाद, टाइप एक्सप्रेशन होना चाहिए.

किसी enum का टाइप लेबल, enum की हर प्रॉपर्टी पर लागू होता है. उदाहरण के लिए, अगर किसी enum का टाइप number है, तो उसकी हर प्रॉपर्टी एक संख्या होनी चाहिए. अगर किसी enum का टाइप शामिल नहीं किया जाता है, तो 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 से, किसी क्लास को दूसरी क्लास से इनहेरिट नहीं किया जा सकता. एनोटेशन से कंपाइलर को यह पता चलता है कि टाइप की जांच के दौरान, वह एक क्लास को दूसरी क्लास की सबक्लास के तौर पर मान सकता है.

इनहेरिटेंस को लागू करने के उदाहरण के लिए, Closure Library फ़ंक्शन 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

यह एनोटेशन सिर्फ़ externs प्रॉपर्टी के एलान में दिख सकता है. प्रॉपर्टी का टाइप तय किया गया है, लेकिन आपको चेतावनी मिले बिना ही इसे कोई भी टाइप असाइन करने का विकल्प मिलता है. प्रॉपर्टी को ऐक्सेस करने पर, आपको तय किए गए टाइप की वैल्यू वापस मिलती है. उदाहरण के लिए, 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;
}
डिस्ट्रक्चरिंग पैटर्न वाले पैरामीटर के लिए, टाइप एनोटेशन के बाद, किसी भी ऐसे नाम का इस्तेमाल किया जा सकता है जो मान्य JS आइडेंटिफ़ायर हो.
/**
 * @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 देखें).

अगर externs में मौजूद नहीं है, तो फ़ंक्शन की कोई रिटर्न वैल्यू नहीं होती. ऐसे में, @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

इस टैग का इस्तेमाल, किसी फ़ंक्शन से मिले अपवादों को दस्तावेज़ में शामिल करने के लिए किया जाता है. फ़िलहाल, टाइप चेकर इस जानकारी का इस्तेमाल नहीं करता है. इसका इस्तेमाल सिर्फ़ यह पता लगाने के लिए किया जाता है कि किसी externs फ़ाइल में बताए गए फ़ंक्शन के साइड इफ़ेक्ट हैं या नहीं.

उदाहरण के लिए:

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

यह ज़्यादा जटिल टाइप के लिए, उपनाम तय करता है. फ़िलहाल, typedefs को सिर्फ़ टॉप लेवल पर तय किया जा सकता है, न कि फ़ंक्शन के अंदर. हमने टाइप इन्फ़रेंस की नई सुविधा में इस समस्या को ठीक कर दिया है.

उदाहरण के लिए:

/** @typedef {(string|number)} */
goog.NumberLike;

/** @param {goog.NumberLike} x A number or a string. */
goog.readNumber = function(x) {
  ...
}
@unrestricted

इससे पता चलता है कि क्लास न तो @struct टाइप की है और न ही @dict टाइप की. यह डिफ़ॉल्ट रूप से होता है. इसलिए, आम तौर पर इसे साफ़ तौर पर लिखने की ज़रूरत नहीं होती. हालांकि, अगर 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 यह वादा नहीं करता कि वह आपके प्रोग्राम में मौजूद हर एक्सप्रेशन का टाइप पता लगा पाएगा. यह सबसे सही तरीके से काम करता है. इसके लिए, यह देखता है कि वैरिएबल का इस्तेमाल कैसे किया गया है और उनके एलान से जुड़े टाइप एनोटेशन कैसे हैं. इसके बाद, यह टाइप इन्फ़रेंस एल्गोरिदम का इस्तेमाल करके, ज़्यादा से ज़्यादा एक्सप्रेशन के टाइप का पता लगाता है. इनमें से कुछ एल्गोरिदम आसान होते हैं ("अगर x कोई संख्या है और हमें y = x; दिखता है, तो y भी एक संख्या है"). कुछ नियम ज़्यादा घुमा-फिराकर बताए जाते हैं ("अगर f's first parameter is documented as a callback that must take a number, and we see f(function(x) { /** ... */ });, then x must be a number").

ऑपरेटर का नाम सिंटैक्स के उदाहरण ब्यौरा
नाम टाइप करें {boolean}
{Window}
{goog.ui.Menu}
किसी टाइप का नाम बताता है.
ऐप्लिकेशन का टाइप {Array<string>}
स्ट्रिंग का कलेक्शन.

{Object<string, number>}
यह एक ऐसा ऑब्जेक्ट है जिसमें कुंजियां स्ट्रिंग होती हैं और वैल्यू संख्याएं होती हैं.

टाइप को टाइप आर्ग्युमेंट के सेट के साथ पैरामीटर में बदलता है. Java के जेनेरिक से मिलता-जुलता है.
यूनियन टाइप {(number|boolean)}
कोई संख्या या बूलियन.

ब्रैकेट का इस्तेमाल करना ज़रूरी है.
इससे पता चलता है कि किसी वैल्यू का टाइप A या टाइप B हो सकता है.
रिकॉर्ड टाइप {{myNum: number, myObject}}
एक एनॉनिमस टाइप, जिसमें myNum नाम की एक प्रॉपर्टी है. इसकी वैल्यू का टाइप number है. साथ ही, इसमें myObject नाम की एक प्रॉपर्टी है. इसकी वैल्यू का टाइप कोई भी हो सकता है.

इससे पता चलता है कि वैल्यू में बताए गए टाइप की वैल्यू वाले सदस्य मौजूद हैं.

ब्रैसिस, टाइप सिंटैक्स का हिस्सा हैं. उदाहरण के लिए, length प्रॉपर्टी वाले ऑब्जेक्ट के Array को दिखाने के लिए,
Array<{length}> लिखा जा सकता है. बाईं ओर दिए गए उदाहरण में, बाहरी ब्रेसिज़ से पता चलता है कि यह एक टाइप एक्सप्रेशन है. वहीं, अंदरूनी ब्रेसिज़ से पता चलता है कि यह एक रिकॉर्ड टाइप है.

नल वैल्यू स्वीकार करने वाला टाइप {?number}
कोई संख्या या null.

इससे पता चलता है कि वैल्यू टाइप A या null है.

सभी ऑब्जेक्ट टाइप डिफ़ॉल्ट रूप से नल हो सकते हैं. भले ही, उन्हें Nullable ऑपरेटर के साथ घोषित किया गया हो या नहीं. ऑब्जेक्ट टाइप को इस तरह से परिभाषित किया जाता है: फ़ंक्शन, स्ट्रिंग, संख्या या बूलियन के अलावा कुछ भी. किसी ऑब्जेक्ट टाइप को नॉन-नलेबल बनाने के लिए, Non-nullable ऑपरेटर का इस्तेमाल करें.

नॉन-नलेबल टाइप {!Object}
एक ऑब्जेक्ट है, लेकिन कभी भी null वैल्यू नहीं है.

इससे पता चलता है कि वैल्यू टाइप A है और शून्य नहीं है.

फ़ंक्शन और सभी वैल्यू टाइप (बूलियन, संख्या, और स्ट्रिंग) डिफ़ॉल्ट रूप से नॉन-नलेबल होते हैं. भले ही, उन्हें Non-nullable ऑपरेटर के साथ एलान किया गया हो या नहीं. किसी वैल्यू या फ़ंक्शन टाइप को नल वैल्यू के तौर पर इस्तेमाल करने के लिए, Nullable ऑपरेटर का इस्तेमाल करें.

फ़ंक्शन टाइप {function(string, boolean)}
यह फ़ंक्शन दो पैरामीटर (एक स्ट्रिंग और एक बूलियन) लेता है. इसकी रिटर्न वैल्यू के बारे में जानकारी नहीं है.
यह फ़ंक्शन और फ़ंक्शन के पैरामीटर के टाइप तय करता है.
फ़ंक्शन का रिटर्न टाइप {function(): number}
यह एक ऐसा फ़ंक्शन है जो कोई पैरामीटर नहीं लेता और एक संख्या दिखाता है.
किसी फ़ंक्शन की रिटर्न वैल्यू का टाइप तय करता है.
फ़ंक्शन this टाइप {function(this:goog.ui.Menu, string)}
यह फ़ंक्शन एक पैरामीटर (एक स्ट्रिंग) लेता है और goog.ui.Menu के कॉन्टेक्स्ट में काम करता है.
फ़ंक्शन में this की वैल्यू का टाइप तय करता है.
फ़ंक्शन new टाइप {function(new:goog.ui.Menu, string)}
यह फ़ंक्शन एक पैरामीटर (एक स्ट्रिंग) लेता है. साथ ही, 'new' कीवर्ड के साथ कॉल किए जाने पर, 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=)}
यह फ़ंक्शन, एक वैकल्पिक, नल हो सकने वाली स्ट्रिंग और एक वैकल्पिक संख्या को आर्ग्युमेंट के तौर पर लेता है.
इससे पता चलता है कि फ़ंक्शन टाइप में कोई तर्क ज़रूरी नहीं है. फ़ंक्शन कॉल में, वैकल्पिक आर्ग्युमेंट को शामिल नहीं किया जा सकता. आर्ग्युमेंट की सूची में, ज़रूरी नहीं है कि आर्ग्युमेंट, ज़रूरी आर्ग्युमेंट से पहले हो.
ALL टाइप {*} इससे पता चलता है कि वैरिएबल किसी भी टाइप का हो सकता है.
UNKNOWN टाइप {?} इससे पता चलता है कि वेरिएबल किसी भी टाइप का हो सकता है. साथ ही, कंपाइलर को इसके किसी भी इस्तेमाल की टाइप-जांच नहीं करनी चाहिए.

टाइप कास्टिंग

किसी वैल्यू को किसी खास टाइप में कास्ट करने के लिए, इस सिंटैक्स का इस्तेमाल करें

/** @type {!MyType} */ (valueExpression)
एक्सप्रेशन के चारों ओर मौजूद कोष्ठक हमेशा ज़रूरी होते हैं.

जेनरिक टाइप

Java की तरह ही, Closure Compiler में सामान्य टाइप, फ़ंक्शन, और तरीकों का इस्तेमाल किया जा सकता है. जेनेरिक, अलग-अलग टाइप के ऑब्जेक्ट पर काम करते हैं. साथ ही, कंपाइल-टाइम टाइप की सुरक्षा को बनाए रखते हैं.

जेनेरिक का इस्तेमाल करके, सामान्य कलेक्शन लागू किए जा सकते हैं. इनमें किसी खास टाइप के ऑब्जेक्ट के रेफ़रंस होते हैं. साथ ही, सामान्य एल्गोरिदम लागू किए जा सकते हैं. ये किसी खास टाइप के ऑब्जेक्ट पर काम करते हैं.

जेनेरिक टाइप का एलान करना

टाइप के कंस्ट्रक्टर (क्लास के लिए) या इंटरफ़ेस के एलान (इंटरफ़ेस के लिए) में @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> टाइप की ज़रूरत है, तो X और Y अलग-अलग टाइप होने पर, Foo<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