When should there be a dot in JSDoc generics?

From a syntax point of view all these types expressions are valid when you run jsdoc index.js

/** @param {Array} x */
const a = x => x;

/** @param {Array.<string>} x */
const b = x => x;

/** @param {Array<string>} x */
const c = x => x;

/** @param {string[]} x */
const d = x => x;

It should be noted that the Google Closure Compiler doesn't seem to recognise the {<type>[]} type expression e.g. if you compile this:

/** @param {string[]} x */
const a = x => x;

You get the following warning:

JSC_TYPE_PARSE_ERROR: Bad type annotation. expected closing } See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler for more information. at line 1 character 18
/** @param {string[]} x */
                  ^
JSC_TYPE_PARSE_ERROR: Bad type annotation. expecting a variable name in a @param tag. See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler for more information. at line 1 character 18
/** @param {string[]} x */
                  ^

See this Google Closure Compiler fiddle.

The static type checker in VS Code will complain about the last three function calls:

// @ts-check

/** @param {Array} x */
const a = x => x;

/** @param {Array.<string>} x */
const b = x => x;

/** @param {Array<string>} x */
const c = x => x;

/** @param {string[]} x */
const d = x => x;

a(['foo', 3]); // OK (we just need an array)
b(['foo', 3]); // ERR: 3 is not a string
c(['foo', 3]); // ERR: 3 is not a string
d(['foo', 3]); // ERR: 3 is not a string

So it pretty much seems like that {Array.<string>} and {Array<string>} are the same thing.

Personally I would favour {Array<string>} over {Array.<string>}. Why? The dot . is also a "namespace" separator:

/** @namespace */
const Burrito = {};

/** @constructor */
Burrito.beef = function () {};

/** @param {Burrito.beef} x */
const a = x => x;

a("foo");
a(new Burrito.beef());

The Google Closure compiler will issue a warning about the first call (the second call is fine):

JSC_TYPE_MISMATCH: actual parameter 1 of a does not match formal parameter
found   : string
required: (Burrito.beef|null) at line 10 character 2
a("foo");
  ^

See this Google Closure Compiler fiddle.

If {Array<string>} and {Array.<string>} are genuinely the same thing (and I believe that to be true) then I would favour the former over the latter so as to keep the meaning of the . character unambiguous.