Why TS is complaining about this:
/** * @template X * @type {function(X): X} */ const identity1 = (x) => x; /** * @template X * @type {function(X): X} */ const identity2 = (x) => identity1(x);
TypeScript Error Message:
Type 'X' is not assignable to type 'X'. Two different types with this name exist, but they are unrelated. 'X' could be instantiated with an arbitrary type which could be unrelated to 'X'.ts(2719) graph.mjs(4, 14): This type parameter might need an `extends X` constraint. const identity1: (arg0: X) => X @template X @type — {function(X): X}
However, when changing the @type
using @param
and @return
it works fine:
/** * @template X * @param {X} x * @returns {X} */ const identity1 = (x) => x; /** * @template X * @type {function(X): X} */ const identity2 = (x) => identity1(x);
I do not understand why. The documentation makes no mention of how these two signatures interact differently with generic types.
Use the
@type
tag to refer to the type range limited to curly braces. That is,@type {function(X): X}
does not refer to the generic type because we referenced X outside the scope. At least that's my interpretation. Regardless, extracting the provided type from@type
is not supported.However, you can use
@typedef
to override functions: