JSDoc:属性“value”在类型“EventTarget”上不存在。

9
我正在使用纯JavaScript和TypeScript作为预处理器JSDoc相结合。在后端中(例如在使用NodeJS时),这基本上可以完美运行。 然而,当我将其与DOM对象一起使用时,情况会变得有点棘手。 例如:假设我有一个HTML输入字段,我捕获input事件并想要使用e.target.value访问输入的值:
/**
 * Log data on input
 *
 * @param {Event} e
 */
let handleEvent = function(e){
    console.log(e.target.value);
};

document.getElementById("my-input").addEventListener("input", handleEvent);

这会导致TS警告:

类型“EventTarget”上不存在属性“value”

如下所示:

TypeScript Warning

现在我的问题是,正确的@param注释是什么?
到目前为止,我已经尝试了EventInputEventHTMLInputElement
我不想使用类型断言。相反,我想知道如何直接在函数注释中指定它,这样我就不必像这里建议的那样为每个e.target.value的出现单独设置@type
1个回答

16

您可以像这样编写您的 @param 注释:

/**
 * Log data on input
 *
 * @param {Event & { target: HTMLInputElement }} e
 */
let handleEvent = function(e){
    console.log(e.target.value);
};

然后你将获得正确类型的完全支持:

1

这种方法之所以有效,是因为您基本上是通过新的目标属性“扩展”了Event类 - 该属性已经存在,因此它将被我们的新类型覆盖。

和号本身不是jsdoc运算符,而是TypeScript中的运算符。 因此,如果您继续将TypeScript用作预处理器,则此方法才能正常工作。 有关更详细的解释,请参见此处


遗憾的是,与类型断言相比,这种方法并没有减少太多打字。这种方法是合理的,但它给人一种绕过问题的感觉。不过,如果“Event”/“InputEvent”没有通用类型参数(似乎确实没有),我不知道你还能做什么。 - T.J. Crowder
@T.J.Crowder 在我看来,如果在函数体中经常使用 e,实际上键入的字符会更少。对我而言,这并不像是一种变通方法,因为我明确声明了参数的类型。我能想到的唯一的“变通方法”就是访问 this 而不是 e。尽管如此,我对这个解决方案感到非常满意 :) - NullDev
1
@NullDev - 你可以将 target 取到本地一次。var target = /** @type {HTMLInputElement} */ (e.target); 但是这个 & 解决方案与使用通用类型参数几乎相同(实际上,现在我想想,我不确定类型参数除了更简洁外还能提供什么),所以看起来很不错。 :-) - T.J. Crowder
3
正如您所提到的,它只适用于TypeScript,而不是纯JS,仅使用JSDoc。 在这种情况下,技巧适用于函数,但在调用addEventListener(handleEvent)时不起作用。 假设我们想要使用target和originalTarget。 JSDoc在参数上输出此错误:类型“MouseEvent”的参数不能赋给类型“MouseEvent&{originalTarget:HTMLInputElement; target:HTMLInputElement;}”的参数。 在类型“MouseEvent”中缺少属性“originalTarget”,但在类型“{originalTarget:HTMLInputElement; target:HTMLInputElement;}”中需要。ts(2345) - fips

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接