क्लोज़र कंपाइलर के लिए JavaScript की व्याख्या करना

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

खास जानकारी

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

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

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

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

JSDoc टैग

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

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

टैग जानकारी
@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 टैग के बाद एक टाइप एक्सप्रेशन होना चाहिए.

ईनम का प्रकार लेबल, ईनम की हर प्रॉपर्टी पर लागू होता है. उदाहरण के लिए, अगर किसी ईनम का टाइप 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} का मतलब है "कंस्ट्रक्टर फ़ू".

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;
}
इस तरह के पैरामीटर से,
/**
 * @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 टैग के साथ टाइप एक्सप्रेशन का इस्तेमाल करें.

कोड में जितनी ज़्यादा जानकारी दी जाएगी, कंपाइलर ज़्यादा से ज़्यादा ऑप्टिमाइज़ेशन का इस्तेमाल कर सकेंगे और उतनी ही ज़्यादा गलतियां पकड़ पाएंगे.

कंपाइलर आपके प्रोग्राम की टाइप-चेकिंग के लिए इन एनोटेशन का इस्तेमाल करता है. ध्यान दें कि Close कंपाइलर यह वादा नहीं करता है कि यह आपके प्रोग्राम में हर एक्सप्रेशन का टाइप तय कर पाएगा. यह सबसे अच्छा काम करता है. इसके लिए, वैरिएबल के इस्तेमाल और उनके एलान में अटैच किए गए एनोटेशन के बारे में पता लगाया जाता है. फिर यह ज़्यादा से ज़्यादा एक्सप्रेशन का टाइप पता करने के लिए, कई तरह के अनुमान वाले एल्गोरिदम का इस्तेमाल करता है. इनमें से कुछ एल्गोरिदम सादगी भरे हैं (अगर x एक संख्या है और हमें y = x; दिखता है, तो y एक संख्या है). कुछ ज़्यादा इंडायरेक्ट होते हैं ("अगर f का पहला पैरामीटर कॉलबैक के रूप में दर्ज किया गया है, जिसे संख्या माननी है, और हम f(function(x) { /** ... */ }); देखते हैं, तो x संख्या होना चाहिए").

ऑपरेटर का नाम सिंटैक्स के उदाहरण जानकारी
नाम लिखें {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 टाइप A या null है.

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

गैर-शून्य प्रकार का {!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=)}
ऐसा फ़ंक्शन जो आर्ग्युमेंट के तौर पर एक वैकल्पिक, शून्य होने वाली स्ट्रिंग, और एक वैकल्पिक संख्या लेता है.
इससे पता चलता है कि फ़ंक्शन टाइप में आर्ग्युमेंट ज़रूरी नहीं है. फ़ंक्शन कॉल से एक वैकल्पिक आर्ग्युमेंट हटाया जा सकता है. एक वैकल्पिक आर्ग्युमेंट, आर्ग्युमेंट लिस्ट में मौजूद ऐसे आर्ग्युमेंट से पहले नहीं हो सकता जो ज़रूरी न हो.
ALL टाइप {*} इससे पता चलता है कि वैरिएबल किसी भी टाइप का हो सकता है.
अज्ञात प्रकार {?} यह बताता है कि वैरिएबल को हर तरह के वैरिएबल पर ले जाया जा सकता है. साथ ही, कंपाइलर को इसके किसी भी टाइप की जांच नहीं करनी चाहिए.

प्रकार कास्ट करना

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

/** @type {!MyType} */ (valueExpression)
एक्सप्रेशन के आस-पास वाले ब्रैकेट हमेशा ज़रूरी होते हैं.

जेनेरिक टाइप

Java की तरह, Closure कंपाइलर सामान्य प्रकार, फ़ंक्शन और विधियों का समर्थन करता है. जेनरिक, कई तरह के ऑब्जेक्ट के लिए काम करते हैं. साथ ही, कंपाइल के समय की सुरक्षा देते हैं.

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

सामान्य टाइप का एलान

टाइप के कंस्ट्रक्टर (कक्षा के लिए) में @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.

जेनरिक टाइप का अंतर

क्लोज़र कंपाइलर, सामान्य जेनरिक टाइपिंग लागू करता है. इसका मतलब है कि अगर किसी संदर्भ में 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