-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Types in the Closure Type System
When documenting a type in JSDoc, be as specific and accurate as possible. The types we support are based on the EcmaScript 4 spec.
The ES4 proposal contained a language for specifying JavaScript types. We use this language in JsDoc to express the types.
Syntax Name | Syntax | Description | Allows null? | Deprecated Syntaxes |
---|---|---|---|---|
Primitive Type |
There are 5 primitive types in JavaScript:
{null} ,
{undefined} ,
{boolean} ,
{number} , and
{string} .
|
Simply the name of a type. | Only{null} .The other primitive types are not nullable. |
|
Instance Type |
{Object} An instance of Object, or null. {Function} An instance of Function, or null. {EventTarget} An instance of a constructor that implements the EventTarget interface, or null. |
An instance of a constructor or interface function.
By default, instance types will accept null, but including the
Whenever possible, avoid using |
Yes. | |
Enum Type |
{goog.events.EventType} One of the properties of the object literal initializer of goog.events.EventType .
|
An enum must be initialized as an object literal, or as an
alias of another enum, annotated with the Note that this is one of the few things in our type system that were not in the ES4 spec. |
Depends on the referenced type.@enum {string}
or@enum {number} is not nullable by default,
while@enum {Object} is. |
|
Type Application |
{?Array<string>} A nullable array of strings. {!Object<string, number>} A non-null object in which the keys are strings and the values are numbers. {!goog.structs.Set<!YourType>} A non-null Set of non-null instances of YourType. |
Parameterizes a type, by applying a set of type arguments
to that type. The idea is analogous to generics in Java. The
dot before the< (e.g.
{!Array.<string>} ) is optional.
|
Depends on the type being parameterized (?Object
vs.!Object ) and on the type arguments used to
parameterize it (?YourType vs.
!YourType ,number vs.
?number ).
|
|
Type Union |
{(number|boolean)} A number or a boolean. |
Indicates that a value might have type A OR type B.
|
Only when any of the types in the union is already nullable. |
{(number,boolean)} ,{(number||boolean)}
|
Nullable type |
{?number} A number or null. |
Shorthand for the union of the null type with any other type. This is just syntactic sugar. Note that the following are already nullable, and thus
prepending ?Object, ?Array, ?Function |
Yes. |
{number?}
|
Non-nullable type |
{!Object} An Object, but never the null value.
|
Filters null out of nullable types. Most often used with instance types, which are nullable by default. Note that the following are already non-nullable, and thus
prepending !number, !string, !boolean, !{foo: string}, !function() |
No. |
{Object!}
|
Record Type |
{{myNum: number, myObject}}
An anonymous type with the given type members. |
Indicates that the value has the specified members with the
specified types. In this case, Notice that the braces are part of the type syntax. For
example, to denote an |
No. | |
Function Type |
{function(string, boolean)} A function that takes two arguments (a string and a boolean), and has an unknown return value. |
Specifies a function. Also note the difference between |
No. | |
Function Return Type |
{function(): number} A function that takes no arguments and returns a number. |
Specifies a function return type. |
function(...) is not nullable. Nullability
of the return type is determined by the type itself. |
|
Functionthis Type |
{function(this:goog.ui.Menu, string)} A function that takes one argument (a string), and executes in the context of a goog.ui.Menu. |
Specifies the context type of a function type. |
function(...) is not nullable.
this can be null. |
|
Functionnew Type |
{function(new:goog.ui.Menu, string)} A constructor that takes one argument (a string), and creates a new instance of goog.ui.Menu when called with the 'new' keyword. |
Specifies the constructed type of a constructor. |
function(...) is not nullable. |
|
Variable arguments |
{function(string, ...number): number} A function that takes one argument (a string), and then a variable number of arguments that must be numbers. |
Specifies variable arguments to a function. |
function(...) is not nullable. Nullability
of the arguments is determined by the type annotation
after the...
|
|
Variable arguments (in@param annotations)
|
@param {...number} var_args A variable number of arguments to an annotated function. |
Specifies that the annotated function accepts a variable number of arguments. | Determined by the type annotation after the ellipsis. | |
Functionoptional arguments |
{function(?string=, number=)} A function that takes one optional, nullable string and one optional number as arguments. The = syntax is
only forfunction type declarations.
|
Specifies optional arguments to a function. |
function(...) is not nullable. Nullability of
arguments is determined by the unadorned type annotation.
Seenullable vs. optional for more
information. |
|
Functionoptional arguments
(in@param annotations)
|
@param {number=} opt_argument An optional parameter of type number .
|
Specifies that the annotated function accepts an optional argument. | Same as above. | |
The ALL type | {*} |
Indicates that the variable can take on any type. | Yes. | |
The UNKNOWN type | {?} |
Indicates that the variable can take on any type, and the compiler should not type-check any uses of it. | Yes. |
Type Example | Value Examples | Description |
---|---|---|
number |
1 1.0 -5 1e5 Math.PI |
|
Number |
new Number(true) |
Number object |
string |
'Hello' "World" String(42) |
String value |
String |
new String('Hello') new String(42) |
String object |
boolean |
true false Boolean(0) |
Boolean value |
Boolean |
new Boolean(true) |
Boolean object |
RegExp |
new RegExp('hello') /world/g |
|
Date |
new Date new Date() |
|
preferred: null deprecated: Null |
null |
|
preferred: undefined deprecated: Undefined |
undefined |
|
void |
function f() { return; } |
No return value |
Array |
['foo', 0.3, null] [] |
Untyped Array |
Array<number> |
[11, 22, 33] |
An Array of numbers |
Array<Array<string>> |
[['one', 'two', 'three'], ['foo', 'bar']] |
Array of Arrays of strings |
Object |
{} {foo: 'abc', bar: 123, baz: null} |
|
Object<string> |
{'foo': 'bar'} |
An Object in which the values are strings. |
Object<number, string> |
var obj = {}; obj[1] = 'bar'; |
An Object in which the keys are numbers and the values are
strings.Note that in JavaScript, the keys are always
implicitly converted to strings, so
obj['1'] == obj[1] .
So the key will always be a string in for...in loops. But the
compiler will verify the type of the key when indexing into
the object.
|
Function |
function(x, y) { return x * y; } |
Function object |
function(number, number): number |
function(x, y) { return x * y; } |
function value |
SomeClass |
/** @constructor */ function SomeClass() {} |
|
SomeInterface |
/** @interface */ function SomeInterface() {} |
|
SomeRecord |
/** @record */ function SomeInterface() {} |
Like an interface, but is checked using structural equality only. Any value with matching properties is convertible to the record type. |
project.MyClass |
/** @constructor */ project.MyClass = function () {} |
|
project.MyEnum |
/** @enum {string} */ project.MyEnum = { /** The color blue. */ BLUE: '#0000dd', /** The color red. */ RED: '#dd0000' }; |
Enumeration JSDoc comments on enum values are optional. |
Element |
document.createElement('div') |
Elements in the DOM. |
Node |
document.body.firstChild |
Nodes in the DOM. |
HTMLInputElement |
htmlDocument.getElementsByTagName('input')[0] |
A specific type of DOM element. |
In cases where type-checking doesn't accurately infer the type of an expression, it is possible to add a type cast comment by adding a type annotation comment and enclosing the expression in parentheses. The parentheses are required.
/** @type {number} */ (x)
Because JavaScript is a loosely-typed language, it is very important to understand the subtle differences between optional, nullable, and undefined function parameters and class properties.
Instances of classes and interfaces are nullable by default. For example, the following declaration
/** * Some class, initialized with a value. * @param {Object} value Some value. * @constructor */ function MyClass(value) { /** * Some value. * @private {Object} */ this.myValue_ = value; }
tells the compiler that themyValue_
property holds
either an Object or null. IfmyValue_
must never be
null, it should be declared like this:
/** * Some class, initialized with a non-null value. * @param {!Object} value Some value. * @constructor */ function MyClass(value) { /** * Some value. * @private {!Object} */ this.myValue_ = value; }
This way, if the compiler can determine that somewhere in the code
MyClass
is initialized with a null value, it will issue
a warning.
You may see type declarations like these in older code:
@type {Object?} @type {Object|null}
Optional parameters to functions may be undefined at runtime, so if they are assigned to class properties, those properties must be declared accordingly:
/** * Some class, initialized with an optional value. * @param {!Object=} opt_value Some value (optional). * @constructor */ function MyClass(opt_value) { /** * Some value. * @private {!Object|undefined} */ this.myValue_ = opt_value; }
This tells the compiler thatmyValue_
may hold an
Object, or remain undefined.
Note that the optional parameteropt_value
is declared
to be of type{!Object=}
, not
{!Object|undefined}
. This is because optional
parameters may, by definition, be undefined. While there is no harm
in explicitly declaring an optional parameter as possibly undefined,
it is both unnecessary and makes the code harder to read.
Finally, note that being nullable and being optional are orthogonal properties. The following four declarations are all different:
/** * Takes four arguments, two of which are nullable, and two of which are * optional. * @param {!Object} nonNull Mandatory (must not be undefined), must not be null. * @param {?Object} mayBeNull Mandatory (must not be undefined), may be null. * ({Object} would mean the same thing, but is not as explicit.) * @param {!Object=} opt_nonNull Optional (may be undefined), but if present, * must not be null! * @param {?Object=} opt_mayBeNull Optional (may be undefined), may be null. * ({Object=} would mean the same thing, but is not as explicit.) */ function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) { // ... };
Sometimes types can get complicated. A function that accepts content for an Element might look like:
/** * @param {string} tagName * @param {(string|Element|Text|Array<Element>|Array<Text>)} contents * @return {!Element} */ goog.createElement = function(tagName, contents) { ... };
You can define commonly used type expressions with a
@typedef
tag. For example,
/** @typedef {(string|Element|Text|Array<Element>|Array<Text>)} */ goog.ElementContent; /** * @param {string} tagName * @param {goog.ElementContent} contents * @return {!Element} */ goog.createElement = function(tagName, contents) { ... };
The compiler has limited support for template types. It can only
infer the type ofthis
inside an anonymous function
literal from the type of thethis
argument and whether the
this
argument is missing.
/** * @param {function(this:T, ...)} fn * @param {T} thisObj * @param {...*} var_args * @template T */ goog.bind = function(fn, thisObj, var_args) { ... }; // Possibly generates a missing property warning. goog.bind(function() { this.someProperty; }, new SomeClass()); // Generates an undefined this warning. goog.bind(function() { this.someProperty; });