//@ts-check and DOM 元素属性报错

//@ts-check and DOM element properties gives an error

我有一些简单的浏览器端 JS 代码,我想我会尝试使用 @ts-check 来找出任何问题。发现了一些有效的错误,我也添加了 js-doc 参数类型信息。我不想要转译步骤,所以这需要是香草 Javascript.

当我访问 DOM 元素属性时出现错误,因为 TS 不知道这些元素的真实类型。

s.YWindows = document.getElementById("rows-input").valueAsNumber

给...

Property 'valueAsNumber' does not exist on type 'HTMLElement'

我想我可以使用 JSDoc 类型提示来解决这个问题,但它只会解决问题。

     /** @type {HTMLInputElement} */
    let r =  document.getElementById("rows-input")
    s.YWindows = r.valueAsNumber
Type 'HTMLElement' is missing the following properties from type 'HTMLInputElement': accept, align, alt, autocomplete, and 52 more.

建议,还是我必须以某种方式禁用此部分?

(目前)不可能让 TypeScript 理解这种情况。 @types 提示适用于声明的变量,但不要更改初始化其值的函数的 return 类型。

您可以在一行上方使用 //@ts-ignore 让 TS 忽略可能出现在该行中的 所有 错误。例如:

/** @type {{HTMLInputElement}} */
//@ts-ignore
let r =  document.getElementById("rows-input");

s.YWindows = r.valueAsNumber;

这仍然会告诉 TS r 有一个 HTMLInputElement 类型,但它会忽略 r 的类型和 getElementById 的 return类型。 这样做的一个缺点是您最终可能会经常使用 //@ts-ignore

TypeScript 编译器在使用 JSDoc 语法时支持 inline type casting。来自 link:

TypeScript borrows cast syntax from Google Closure. This lets you cast types to other types by adding a @type tag before any parenthesized expression.

/**
 * @type {number | string}
 */
var numberOrString = Math.random() < 0.5 ? "hello" : 100;
var typeAssertedNumber = /** @type {number} */ (numberOrString);

You can even cast to const just like TypeScript:

let one = /** @type {const} */(1);

这是一个解决问题细节的例子:

TS Playground

/** @type {{ YWindows?: number }} */
const s = {};

// It's not safe to assume that the ID exists in the document,
// so null must be included in the union:
const input = /** @type {HTMLInputElement | null} */(document.getElementById("rows-input"));

if (input) {
  s.YWindows; // number | undefined
  s.YWindows = input.valueAsNumber;
  s.YWindows; // number
}

s.YWindows; // number | undefined