function main( context ) {
	var options;
	var source;
	var opts;

	source = context.getSourceCode();
	opts = copy( DEFAULTS );
	options = context.options[ 0 ];
	if ( hasOwnProp( options, 'types' ) ) {
		opts.types = options.types;
	}

	/**
	* Reports the error message.
	*
	* @private
	* @param {string} old - name of type with typo
	* @param {string} replacement - correct type name
	* @param {Object} loc - lines of code (object with `start` and `end` properties)
	*/
	function report( old, replacement, loc ) {
		var msg = '"'+old+'" type definition should be "'+replacement+'"';
		context.report({
			'node': null,
			'message': msg,
			'loc': loc
		});
	}

	/**
	* Checks whether JSDoc comments likely have typos in type definitions of their JSDoc tags.
	*
	* @private
	* @param {ASTNode} node - node to examine
	*/
	function validate( node ) {
		var jsdoc;
		var tags;
		var tag;
		var ast;
		var i;

		jsdoc = findJSDoc( source, node );
		if ( isObject( jsdoc ) ) {
			ast = doctrine.parse( jsdoc.value, OPTS );
			tags = ast.tags;
			for ( i = 0; i < tags.length; i++ ) {
				tag = tags[ i ];
				if (
					tag.title === 'param' ||
					tag.title === 'returns' ||
					tag.title === 'throws' ||
					tag.title === 'type'
				) {
					if ( tag.type ) {
						likelyHasTypo( tag.type, jsdoc.loc );
					} else {
						context.report({
							'message': '`@'+tag.title+'` is missing type definition',
							'loc': jsdoc.loc
						});
					}
				}
			}
		}
	}

	/**
	* Checks and reports whether a type definition likely has a typo.
	*
	* @private
	* @param {Object} type - type definition
	* @param {Object} loc - lines of code (object with `start` and `end` properties)
	* @returns {void}
	*/
	function likelyHasTypo( type, loc ) {
		var replacement;
		var typedef;
		var elem;
		var j;

		if ( type.type === 'OptionalType' ) {
			// Need to go down one more level for optional parameters:
			type = type.expression;
		}
		if ( type.type === 'TypeApplication' ) {
			// Case: type definition with angle brackets such as Array<number>
			typedef = type.expression.name;
			replacement = correctTypedef( typedef );
			if ( replacement ) {
				report( typedef, replacement, loc );
			}
			return likelyHasTypo( type.applications[ 0 ], loc );
		}
		if (
			type.type === 'AllLiteral' ||
			type.type === 'NullLiteral' ||
			type.type === 'UndefinedLiteral'
		) {
			// Return early for wildcard (`*`), `undefined`, and `null`:
			return;
		}
		if ( type.type === 'UnionType' ) {
			// Check individual types of type unions (e.g., `(Date|string)`)...
			for ( j = 0; j < type.elements.length; j++ ) {
				elem = type.elements[ j ];
				if ( elem.type === 'TypeApplication' ) {
					typedef = elem.expression.name;
					replacement = correctTypedef( typedef );
					if ( replacement ) {
						report( typedef, replacement, loc );
					}
					likelyHasTypo( elem.applications[ 0 ], loc );
				} else if (
					elem.type !== 'AllLiteral' &&
					elem.type !== 'NullLiteral' &&
					elem.type !== 'UndefinedLiteral'
				) {
					typedef = elem.name;
					replacement = correctTypedef( typedef );
					if ( replacement ) {
						report( typedef, replacement, loc );
					}
				}
			}
			return;
		}
		typedef = type.name;
		if ( typedef ) {
			replacement = correctTypedef( typedef );
			if ( replacement ) {
				report( typedef, replacement, loc );
			}
		}
	}

	/**
	* Returns a corrected type definition if supplied a type definition with a typo.
	*
	* @private
	* @param {string} typedef - type definition
	* @returns {(string|null)} correct type definition or `null`
	*/
	function correctTypedef( typedef ) {
		var diff;
		var min;
		var val;
		var i;

		min = PINF;
		for ( i = 0; i < opts.types.length; i++ ) {
			diff = editDistance( typedef, opts.types[ i ] );
			if ( diff === 0 ) {
				return null;
			}
			if ( diff < min ) {
				min = diff;
				val = opts.types[ i ];
			}
		}
		if ( min <= THRESHOLD ) {
			return val;
		}
		return null;
	}

	return {
		'FunctionExpression:exit': validate,
		'FunctionDeclaration:exit': validate,
		'VariableDeclaration:exit': validate,
		'ExpressionStatement:exit': validate
	};
}
Rule for catching typos in type definitions of JSDoc tags.

@param {Object} context - ESLint context
@returns {Object} validators