Published on

TypeScript - DOM, Type Assertions

Authors
  • avatar
    Name
    Deng Hua
    Twitter

目录

TypeScript's Non-Null Assertion Operator(非空断言操作符)

The non-null assertion operator is a concise way of avoiding unnecessary null and undefined checks in our code. We should only use this when we definitely know the variable or expression can't be null or undefined.

来看一个栗子

const btn = document.getElementById('btn')

btn.addEventListener('click', () => { // ❌ “btn”可能为 “null”。
  console.log('clicked')
})

变量btn的类型为HTMLElement | null,因为TS并不知道DOM中是否真实存在ID为btn的元素,因此为一个联合类型。

除非使用?操作符

const btn = document.getElementById('btn')

btn?.addEventListener('click', () => {
  console.log('clicked')
})

当然我们也可以使用类型断言

const btn = document.getElementById('btn')!

btn.addEventListener('click', () => {
  console.log('clicked')
})

Type Assertions

Sometimes you might have more specific information about a value's type, and you want to make sure Typescript knows it too. You can assert a value's type by using the 'as' keyword, followed by the specific type you want to assert.

有时,您可能有关于值类型的更具体信息,并且您希望确保Typescript也知道它。您可以使用“as”关键字断言值的类型,然后是要断言的特定类型。

如下例:

const myStery: unknown = 'hello'

const numChars = myStery.length // ❌ “myStery”的类型为“未知”

某些情况下,比如使用Fetch获取远程数据时,TS无法明确返回值的类型,但“你”比TS明确知道返回值的类型,这时可以使用类型断言

const myStery: unknown = 'hello'

const numChars = (myStery as string).length

现在,typescript就会把myStery当成一个string类型了。

Type Assertions With the DOM

如下一个场景,我们使用getElementById获取了一个input元素,但此时想进一步获取inputvalue属性时,TS报错了。

const input = document.getElementById('input')!

input.value // ❌ 类型“HTMLElement”上不存在属性“value”

我们将鼠标移到input上查看它的类型,发现类型为HTMLElement。上面并不存在value属性。

我们需要告诉TS,它实际上是一个HTMLInputElement

const input = document.getElementById('input')! as HTMLInputElement

input.value

Working With the DOM

对于DOM事件,也有对应事件类型注释

const form = document.querySelector('#form')!
const input = document.querySelector('btn')!

form.addEventListener('submit', (event: SubmitEvent) => {
  // ...
})

input.addEventListener('click', (event: MouseEvent) => {
  // ...
})

lib.dom.d.ts