Checks that types in jsdoc comments are defined. This can be used to check unimported types.
When enabling this rule, types in jsdoc comments will resolve as used
variables, i.e. will not be marked as unused by no-unused-vars
.
In addition to considering globals found in code (or in ESLint-indicated
globals
) as defined, the following tags will also be checked for
name(path) definitions to also serve as a potential "type" for checking
the tag types in the table below:
@callback
, @class
(or @constructor
), @constant
(or @const
),
@event
, @external
(or @host
), @function
(or @func
or @method
),
@interface
, @member
(or @var
), @mixin
, @name
, @namespace
,
@template
(for "closure" or "typescript" settings.jsdoc.mode
only),
@import
(for TypeScript), @typedef
.
The following tags will also be checked but only when the mode is closure
:
@package
, @private
, @protected
, @public
, @static
The following types are always considered defined.
null
,undefined
,void
,string
,boolean
,object
,function
,symbol
number
,bigint
,NaN
,Infinity
any
,*
,never
,unknown
,const
this
,true
,false
Array
,Object
,RegExp
,Date
,Function
Note that preferred types indicated within settings.jsdoc.preferredTypes
will
also be assumed to be defined.
Also note that if there is an error parsing
types for a tag, the function will silently ignore that tag, leaving it to
the valid-types
rule to report parsing errors.
If you define your own tags, you can use settings.jsdoc.structuredTags
to indicate that a tag's name
is "namepath-defining" (and should prevent
reporting on use of that namepath elsewhere) and/or that a tag's type
is
false
(and should not be checked for types). If the type
is an array, that
array's items will be considered as defined for the purposes of that tag.
An option object may have the following keys:
definedTypes
- This array can be populated to indicate other types which are automatically considered as defined (in addition to globals, etc.). Defaults to an empty array.markVariablesAsUsed
- Whether to mark variables as used for the purposes of theno-unused-vars
rule when they are not found to be undefined. Defaults totrue
. May be set tofalse
to enforce a practice of not importing types unless used in code.disableReporting
- Whether to disable reporting of errors. Defaults tofalse
. This may be set totrue
in order to take advantage of only marking defined variables as used.
Context | everywhere |
Tags | augments , class , constant , enum , implements , member , module , namespace , param , property , returns , throws , type , typedef , yields |
Aliases | constructor , const , extends , var , arg , argument , prop , return , exception , yield |
Closure-only | package , private , protected , public , static |
Recommended | true |
Options | definedTypes , disableReporting , markVariablesAsUsed |
Settings | preferredTypes , mode , structuredTags |
The following patterns are considered problems:
/**
* @param {HerType} baz - Foo.
*/
function quux(foo, bar, baz) {
}
// Settings: {"jsdoc":{"preferredTypes":{"HerType":1000}}}
// Message: Invalid `settings.jsdoc.preferredTypes`. Values must be falsy, a string, or an object.
/**
* @param {HerType} baz - Foo.
*/
function quux(foo, bar, baz) {
}
// Settings: {"jsdoc":{"preferredTypes":{"HerType":false}}}
// Message: The type 'HerType' is undefined.
/**
* @param {strnig} foo - Bar.
*/
function quux(foo) {
}
// Message: The type 'strnig' is undefined.
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
*/
function quux(foo, bar) {
}
// "jsdoc/no-undefined-types": ["error"|"warn", {"definedTypes":["MyType"]}]
// Message: The type 'HisType' is undefined.
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
* @param {HerType} baz - Foo.
*/
function quux(foo, bar, baz) {
}
// Settings: {"jsdoc":{"preferredTypes":{"hertype":{"replacement":"HerType"}}}}
// "jsdoc/no-undefined-types": ["error"|"warn", {"definedTypes":["MyType"]}]
// Message: The type 'HisType' is undefined.
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
* @param {HerType} baz - Foo.
*/
function quux(foo, bar, baz) {
}
// Settings: {"jsdoc":{"preferredTypes":{"hertype":{"replacement":false},"histype":"HisType"}}}
// "jsdoc/no-undefined-types": ["error"|"warn", {"definedTypes":["MyType"]}]
// Message: The type 'HerType' is undefined.
/**
* @template TEMPLATE_TYPE
* @param {WRONG_TEMPLATE_TYPE} bar
*/
function foo (bar) {
};
// Settings: {"jsdoc":{"mode":"closure"}}
// Message: The type 'WRONG_TEMPLATE_TYPE' is undefined.
class Foo {
/**
* @return {TEMPLATE_TYPE}
*/
bar () {
}
}
// Message: The type 'TEMPLATE_TYPE' is undefined.
class Foo {
/**
* @return {TEMPLATE_TYPE}
*/
invalidTemplateReference () {
}
}
/**
* @template TEMPLATE_TYPE
*/
class Bar {
/**
* @return {TEMPLATE_TYPE}
*/
validTemplateReference () {
}
}
// Settings: {"jsdoc":{"mode":"typescript"}}
// Message: The type 'TEMPLATE_TYPE' is undefined.
/**
* @type {strnig}
*/
var quux = {
};
// Message: The type 'strnig' is undefined.
/**
* @template TEMPLATE_TYPE_A, TEMPLATE_TYPE_B
*/
class Foo {
/**
* @param {TEMPLATE_TYPE_A} baz
* @return {TEMPLATE_TYPE_B}
*/
bar (baz) {
}
}
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// Message: The type 'TEMPLATE_TYPE_A' is undefined.
/**
* @param {...VAR_TYPE} varargs
*/
function quux (varargs) {
}
// Message: The type 'VAR_TYPE' is undefined.
/**
* @this {Navigator}
*/
function quux () {}
// Settings: {"jsdoc":{"mode":"closure"}}
// Message: The type 'Navigator' is undefined.
/**
* @export {SomeType}
*/
function quux () {}
// Settings: {"jsdoc":{"mode":"closure"}}
// Message: The type 'SomeType' is undefined.
/**
* @aCustomTag {SomeType}
*/
function quux () {}
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":true}}}}
// Message: The type 'SomeType' is undefined.
/**
* @aCustomTag {SomeType}
*/
function quux () {}
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":["aType","anotherType"]}}}}
// Message: The type 'SomeType' is undefined.
/**
* @namepathReferencing SomeType
*/
/**
* @type {SomeType}
*/
// Settings: {"jsdoc":{"structuredTags":{"namepathReferencing":{"name":"namepath-referencing"}}}}
// Message: The type 'SomeType' is undefined.
/**
* @template abc TEMPLATE_TYPE
* @param {TEMPLATE_TYPE} bar
*/
function foo (bar) {
};
// Settings: {"jsdoc":{"mode":"closure"}}
// Message: The type 'TEMPLATE_TYPE' is undefined.
/**
* @suppress {visibility}
*/
function foo () {
}
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// Message: The type 'visibility' is undefined.
/**
* @typedef Todo
* @property description
* @property otherStuff
*/
/**
* @type {Omit<Todo, "description">}
*/
const a = new Todo();
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// Message: The type 'Omit' is undefined.
/**
* Message with {@link NotKnown}
*/
// Message: The type 'NotKnown' is undefined.
/**
* Message with
* a link that is {@link NotKnown}
*/
// Message: The type 'NotKnown' is undefined.
/**
* @abc
* @someTag Message with
* a link that is {@link NotKnown}
*/
// Message: The type 'NotKnown' is undefined.
/**
* This is a {@namepathOrURLReferencer SomeType}.
*/
// Settings: {"jsdoc":{"structuredTags":{"namepathOrURLReferencer":{"name":"namepath-or-url-referencing"}}}}
// Message: The type 'SomeType' is undefined.
/**
* @import BadImportIgnoredByThisRule
*/
/**
* @import LinterDef, { Sth as Something, Another as Another2 } from "eslint"
*/
/**
* @import { Linter } from "eslint"
*/
/**
* @import LinterDefault from "eslint"
*/
/**
* @import {Linter as Lintee} from "eslint"
*/
/**
* @import * as Linters from "eslint"
*/
/**
* @type {BadImportIgnoredByThisRule}
*/
/**
* @type {Sth}
*/
/**
* @type {Another}
*/
// Message: The type 'BadImportIgnoredByThisRule' is undefined.
The following patterns are not considered problems:
/**
* @param {string} foo - Bar.
*/
function quux(foo) {
}
/**
* @param {Promise} foo - Bar.
*/
function quux(foo) {
}
class MyClass {}
/**
* @param {MyClass} foo - Bar.
*/
function quux(foo) {
console.log(foo);
}
quux(0);
const MyType = require('my-library').MyType;
/**
* @param {MyType} foo - Bar.
*/
function quux(foo) {
}
const MyType = require('my-library').MyType;
/**
* @param {MyType} foo - Bar.
*/
function quux(foo) {
}
import {MyType} from 'my-library';
/**
* @param {MyType} foo - Bar.
* @param {object<string, number>} foo
* @param {Array<string>} baz
*/
function quux(foo, bar, baz) {
}
/*globals MyType*/
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
*/
function quux(foo, bar) {
}
/**
* @typedef {object} hello
* @property {string} a - a.
*/
/**
* @param {hello} foo
*/
function quux(foo) {
}
/**
* @param {Array<syntaxError} foo
*/
function quux(foo) {
}
/**
* Callback test.
*
* @callback addStuffCallback
* @param {String} sum - An test integer.
*/
/**
* Test Eslint.
*
* @param {addStuffCallback} callback - A callback to run.
*/
function testFunction(callback) {
callback();
}
/**
*
*
*/
function foo () {
}
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
*/
function quux(foo, bar) {
}
// "jsdoc/no-undefined-types": ["error"|"warn", {"definedTypes":["MyType","HisType"]}]
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
* @param {HerType} baz - Foo.
*/
function quux(foo, bar, baz) {
}
// Settings: {"jsdoc":{"preferredTypes":{"hertype":{"replacement":"HerType"},"histype":"HisType"}}}
// "jsdoc/no-undefined-types": ["error"|"warn", {"definedTypes":["MyType"]}]
/**
* @param {MyType} foo - Bar.
* @param {HisType} bar - Foo.
* @param {HerType} baz - Foo.
*/
function quux(foo, bar, baz) {
}
// Settings: {"jsdoc":{"preferredTypes":{"hertype":{"replacement":"HerType<>"},"histype":"HisType.<>"}}}
// "jsdoc/no-undefined-types": ["error"|"warn", {"definedTypes":["MyType"]}]
/**
* @template TEMPLATE_TYPE
* @param {TEMPLATE_TYPE} bar
* @return {TEMPLATE_TYPE}
*/
function foo (bar) {
};
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @template TEMPLATE_TYPE
*/
class Foo {
/**
* @return {TEMPLATE_TYPE}
*/
bar () {
}
}
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @template TEMPLATE_TYPE
*/
class Foo {
/**
* @return {TEMPLATE_TYPE}
*/
bar () {}
/**
* @return {TEMPLATE_TYPE}
*/
baz () {}
}
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @template TEMPLATE_TYPE_A, TEMPLATE_TYPE_B
*/
class Foo {
/**
* @param {TEMPLATE_TYPE_A} baz
* @return {TEMPLATE_TYPE_B}
*/
bar (baz) {
}
}
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @template TEMPLATE_TYPE_A, TEMPLATE_TYPE_B - Some description
*/
class Foo {
/**
* @param {TEMPLATE_TYPE_A} baz
* @return {TEMPLATE_TYPE_B}
*/
bar (baz) {
}
}
// Settings: {"jsdoc":{"mode":"closure"}}
/****/
/* */
/*** */
/**
*
*/
function quux () {
}
/**
* @typedef {object} BaseObject
*/
/**
* Run callback when hooked method is called.
*
* @template {BaseObject} T
* @param {T} obj - object whose method should be hooked.
* @param {string} method - method which should be hooked.
* @param {(sender: T) => void} callback - callback which should
* be called when the hooked method was invoked.
*/
function registerEvent(obj, method, callback) {
}
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @param {...} varargs
*/
function quux (varargs) {
}
/**
* @param {...number} varargs
*/
function quux (varargs) {
}
class Navigator {}
/**
* @this {Navigator}
*/
function quux () {}
// Settings: {"jsdoc":{"mode":"closure"}}
class SomeType {}
/**
* @export {SomeType}
*/
function quux () {}
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @template T
* @param {T} arg
*/
function example(arg) {
/** @param {T} */
function inner(x) {
}
}
// Settings: {"jsdoc":{"mode":"closure"}}
const init = () => {
/**
* Makes request
* @returns {Promise}
*/
function request() {
return Promise.resolve('success');
}
};
/** Gets a Promise resolved with a given value.
*
* @template ValueType
* @param {ValueType} value Value to resolve.
* @returns {Promise<ValueType>} Promise resolved with value.
*/
exports.resolve1 = function resolve1(value) {
return Promise.resolve(value);
};
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* A function returning the same type as its argument.
*
* @template ValueType
* @typedef {ValueType} ValueFunc
*/
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @aCustomTag {SomeType}
*/
function quux () {}
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":false}}}}
/**
* @aCustomTag {SomeType}
*/
function quux () {}
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":["aType","SomeType"]}}}}
/**
* @namepathDefiner SomeType
*/
/**
* @type {SomeType}
*/
// Settings: {"jsdoc":{"structuredTags":{"namepathDefiner":{"name":"namepath-defining"}}}}
class Test {
/**
* Method.
*
* @returns {this} Return description.
*/
method (): this {
return this;
}
}
/**
* Bad types ignored here and handled instead by `valid-types`.
* @param {string(} foo - Bar.
*/
function quux(foo) {
}
/**
* @template T
* @param {T} arg
* @returns {[T]}
*/
function genericFunctionExample(arg) {
const result = /** @type {[T]} */ (new Array());
result[0] = arg;
return result;
}
// Settings: {"jsdoc":{"mode":"closure"}}
/** @typedef QDigestNode */
class A {
/**
* @template {object} T
* @param {(node: QDigestNode) => T} callback
* @returns {T[]}
*/
map(callback) {
/** @type {T[]} */
let vals;
return vals;
}
}
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @template T
* @param {T} arg
*/
function example(arg) {
/** @param {T} */
function inner(x) {
}
}
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @suppress {visibility}
*/
function foo () {
}
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @template T
*/
export class Foo {
// cast to T
getType() {
const x = "hello";
const y = /** @type {T} */ (x);
return y;
}
}
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @type {const}
*/
const a = 'string';
/**
* @typedef Todo
* @property description
* @property otherStuff
*/
/**
* @type {Omit<Todo, "description">}
*/
const a = new Todo();
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @template A, [B=SomeDefault]
*/
class Foo {
/**
* @param {A} baz
* @return {B}
*/
bar (baz) {
}
}
// Settings: {"jsdoc":{"mode":"typescript"}}
import {MyType} from 'my-library';
/**
* @param {MyType} foo - Bar.
* @param {AnUndefinedType} bar
*/
function quux(foo, bar) {
}
// "jsdoc/no-undefined-types": ["error"|"warn", {"disableReporting":true}]
class MyClass {}
class AnotherClass {}
/**
* A description mentioning {@link MyClass} and {@link AnotherClass | another class} and a URL via [this link]{@link https://www.example.com}.
*/
function quux(foo) {
console.log(foo);
}
quux(0);
class MyClass {}
class AnotherClass {}
/**
* @see A tag mentioning {@link MyClass} and {@link AnotherClass | another class} and a URL via [this link]{@link https://www.example.com}.
*/
function quux(foo) {
console.log(foo);
}
quux(0);
/**
* @import BadImportIgnoredByThisRule
*/
/**
* @import LinterDef, { Sth as Something, Another as Another2 } from "eslint"
*/
/**
* @import { Linter } from "eslint"
*/
/**
* @import LinterDefault from "eslint"
*/
/**
* @import {Linter as Lintee} from "eslint"
*/
/**
* @import * as Linters from "eslint"
*/
/**
* @type {LinterDef}
*/
/**
* @type {Something}
*/
/**
* @type {Another2}
*/
/**
* @type {Linter}
*/
/**
* @type {LinterDefault}
*/
/**
* @type {Lintee}
*/
/**
* @type {Linters}
*/