TypeScript类型断言


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

在这里插入图片描述

TypeScript类型断言概述

类型断言是 TypeScript 中用于补充类型信息的一种写法。TypeScript 会根据代码自动推断变量的类型,但有些时候,它推断出来的类型比较宽泛,并不知道某个值在实际运行时的具体类型。此时,如果我们比 TypeScript 更清楚这个值的真实类型,就可以使用类型断言告诉 TypeScript:请把这个值当作某种具体类型来看待。

类型断言推荐使用 as 语法,基本写法是 值 as 类型。例如,element as HTMLInputElement 表示把 element 当作输入框元素来看待;value as string 表示把 value 当作字符串来看待。断言之后,TypeScript 就会按照断言后的类型进行检查,从而允许访问该类型具有的属性或方法。

类型断言最常见的使用场景之一是 DOM 元素操作。通过 document.querySelector 获取页面元素时,TypeScript 只能知道返回结果是一个页面元素,或者可能是 null,但它不一定知道这个元素具体是不是输入框。如果要访问输入框的 value 属性,就需要先判断元素是否存在,再把它断言为 HTMLInputElement。这样写既说明了元素的具体类型,也避免了元素不存在时继续访问属性的问题。

类型断言也常用于事件对象。后续学习 Vue3 时,经常会处理输入框事件。事件对象中的 event.target 类型比较宽泛,TypeScript 只知道它是事件目标,并不知道它一定是输入框。由于不是所有事件目标都有 value 属性,所以直接访问 event.target.value 可能出现类型错误。如果明确知道事件来自输入框,就可以使用 event.target as HTMLInputElement,再读取输入框的 value

需要特别注意的是,类型断言不是类型转换。类型断言只是告诉 TypeScript 按某种类型检查这个值,它不会改变运行时的数据本身。例如,value as number 不会把字符串 "100" 转换成数字。如果确实要把字符串转换成数字,应该使用 JavaScript 的 Number(value)。同理,如果要把数字转换成字符串,应该使用 String(value),而不是把类型断言当作转换操作。

类型断言和类型标注也不同。类型标注用于提前规定变量、函数参数或函数返回值应该是什么类型,例如 let age: number = 18。类型断言则是在某个具体位置告诉 TypeScript,把当前这个值当作某种类型来看待,例如 const input = element as HTMLInputElement。前者偏向于声明类型规则,后者偏向于补充当前值的具体类型信息。

类型断言虽然有用,但不能随意使用。它相当于告诉 TypeScript:“相信我,这个值就是这个类型。”如果断言错误,TypeScript 可能不会继续提示问题,但代码运行时仍然可能出错。例如,一个实际是标题元素的 DOM 节点,如果被断言为输入框元素,再访问 value 属性,就可能得到不符合预期的结果。因此,只有在确实知道某个值的具体类型时,才适合使用类型断言。

在处理 unknown 类型时,也可以使用类型断言。例如,当一个 unknown 值实际保存的是字符串,并且我们确实知道这一点时,可以写成 value as string,然后访问字符串的 length 属性。不过,对初学者来说,优先通过 typeof 等方式判断类型更加稳妥。只有在上下文已经足够明确时,再使用类型断言。

对于准备学习 Vue3 的初学者来说,类型断言的重点是看懂和理解它在输入事件中的用法。类似 ($event.target as HTMLInputElement).value 的写法,就是把事件目标当作输入框元素,然后读取输入框的值。掌握这一点后,后续阅读 Vue3 中的表单输入、事件处理和 TypeScript 代码时,会更容易理解代码为什么要这样写。

案例源码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>TypeScript 类型断言</title>
</head>
<body>
  <h1>TypeScript 类型断言</h1>

  <p>
    本节学习 TypeScript 中的类型断言。
    类型断言用于告诉 TypeScript:某个值的具体类型比它当前推断出来的类型更明确。
  </p>

  <p>
    在后续学习 Vue3 时,经常会看到类似代码:
  </p>

  <pre><code>($event.target as HTMLInputElement).value</code></pre>

  <p>
    这就是类型断言的典型用法。
    所以,在正式进入 Vue3 之前,需要先理解类型断言的基本含义。
  </p>

  <p>
    说明:本节中的代码是 TypeScript 代码,浏览器不能直接运行。
    当前阶段建议使用 TypeScript 官方在线工具
    <a href="https://www.typescriptlang.org/play/" target="_blank">TypeScript Playground</a>
    测试代码。
  </p>

  <hr>

  <h2>一、为什么需要类型断言</h2>

  <p>
    TypeScript 会根据代码自动推断变量的类型。
    但是,有时候 TypeScript 推断出来的类型比较宽泛,
    它并不知道某个值在实际运行时的具体类型。
  </p>

  <p>
    例如,下面代码通过 <code>document.querySelector</code> 获取页面元素:
  </p>

  <pre><code>const element = document.querySelector("#username");</code></pre>

  <p>
    TypeScript 只能知道 <code>element</code> 是一个页面元素,
    但它不一定知道这个元素具体是不是输入框。
  </p>

  <p>
    如果直接访问 <code>value</code> 属性,可能会出现类型错误。
  </p>

  <pre><code>const element = document.querySelector("#username");

console.log(element.value);</code></pre>

  <p>
    错误原因:
    不是所有页面元素都有 <code>value</code> 属性。
    例如 <code>div</code><code>p</code><code>span</code> 等元素就没有普通输入框那样的 <code>value</code> 属性。
  </p>

  <p>
    如果我们明确知道这个元素就是输入框,
    就可以使用类型断言告诉 TypeScript:
    请把它当作 <code>HTMLInputElement</code> 来看待。
  </p>

  <pre><code>const element = document.querySelector("#username");

const input = element as HTMLInputElement;

console.log(input.value);</code></pre>

  <p>
    这就是类型断言的作用:
    <strong>当我们比 TypeScript 更清楚某个值的具体类型时,可以使用类型断言进行说明。</strong>
  </p>

  <hr>

  <h2>二、类型断言的基本语法</h2>

  <p>
    TypeScript 中推荐使用 <code>as</code> 语法进行类型断言。
  </p>

  <pre><code>值 as 类型</code></pre>

  <p>
    例如:
  </p>

  <pre><code>const input = element as HTMLInputElement;</code></pre>

  <p>
    这句代码表示:
    把 <code>element</code> 当作 <code>HTMLInputElement</code> 类型来看待。
  </p>

  <p>
    再看一个简单例子:
  </p>

  <pre><code>let value: unknown = "hello TypeScript";

let message = value as string;

console.log(message.length);</code></pre>

  <p>
    这段代码中:
  </p>

  <ol>
    <li><code>value</code> 的类型是 <code>unknown</code>,表示暂时不知道具体类型。</li>
    <li>我们明确知道 <code>value</code> 保存的是字符串。</li>
    <li>因此使用 <code>value as string</code> 把它断言为字符串。</li>
    <li>断言后,就可以访问字符串的 <code>length</code> 属性。</li>
  </ol>

  <p>
    当前阶段重点掌握:
  </p>

  <pre><code>变量 as 具体类型</code></pre>

  <hr>

  <h2>三、类型断言不是类型转换</h2>

  <p>
    初学者要特别注意:
    <strong>类型断言不是类型转换。</strong>
  </p>

  <p>
    类型断言只是告诉 TypeScript:
    “请把这个值当作某种类型检查。”
  </p>

  <p>
    它不会真的把数据从一种类型转换成另一种类型。
  </p>

  <pre><code>let value: unknown = "100";

let num = value as number;

console.log(num);</code></pre>

  <p>
    上面代码中,<code>value</code> 实际保存的是字符串 <code>"100"</code>。
    即使写了 <code>value as number</code>,
    它在运行时仍然是字符串,不会自动变成数字。
  </p>

  <p>
    如果真的要把字符串转换成数字,应该使用 JavaScript 的转换方法。
  </p>

  <pre><code>let value = "100";

let num = Number(value);

console.log(num + 1);</code></pre>

  <p>
    对比一下:
  </p>

  <ol>
    <li><code>value as number</code>:只是类型断言,不会改变运行时数据。</li>
    <li><code>Number(value)</code>:是真正的数字转换,会生成数字结果。</li>
  </ol>

  <p>
    所以要记住:
    <strong>类型断言只影响 TypeScript 的类型检查,不负责改变数据本身。</strong>
  </p>

  <hr>

  <h2>四、类型断言常用于 DOM 元素</h2>

  <p>
    在前端开发中,类型断言常用于获取 DOM 元素。
    因为 TypeScript 不一定知道某个元素的具体类型。
  </p>

  <p>
    例如,页面中有一个输入框:
  </p>

  <pre><code>&lt;input id="username" type="text" value="jack"&gt;</code></pre>

  <p>
    在 TypeScript 中获取这个元素:
  </p>

  <pre><code>const element = document.querySelector("#username");</code></pre>

  <p>
    这时 TypeScript 只知道 <code>element</code> 是一个元素,
    不知道它一定是输入框。
  </p>

  <p>
    如果要访问输入框的 <code>value</code>,可以这样写:
  </p>

  <pre><code>const element = document.querySelector("#username");

if (element !== null) {
  const input = element as HTMLInputElement;
  console.log(input.value);
}</code></pre>

  <p>
    这段代码中:
  </p>

  <ol>
    <li><code>document.querySelector("#username")</code> 用于获取页面元素。</li>
    <li><code>if (element !== null)</code> 用于判断元素是否存在。</li>
    <li><code>element as HTMLInputElement</code> 表示把元素当作输入框元素来看待。</li>
    <li>断言为输入框元素后,就可以访问 <code>value</code> 属性。</li>
  </ol>

  <p>
    这种写法比直接断言更安全,因为它先判断了元素是否存在。
  </p>

  <hr>

  <h2>五、类型断言常用于事件对象</h2>

  <p>
    后续学习 Vue3 时,经常会处理输入框事件。
    在事件对象中,<code>event.target</code> 的类型比较宽泛。
  </p>

  <pre><code>function handleInput(event: Event): void {
  console.log(event.target.value);
}</code></pre>

  <p>
    上面代码可能会出现类型错误。
  </p>

  <p>
    错误原因:
    TypeScript 只知道 <code>event.target</code> 是事件目标,
    但不知道它一定是输入框。
    不是所有事件目标都有 <code>value</code> 属性。
  </p>

  <p>
    如果我们明确知道这个事件来自输入框,
    可以使用类型断言。
  </p>

  <pre><code>function handleInput(event: Event): void {
  const input = event.target as HTMLInputElement;

  console.log(input.value);
}</code></pre>

  <p>
    这段代码中:
  </p>

  <ol>
    <li><code>event</code> 是事件对象。</li>
    <li><code>event.target</code> 表示触发事件的目标元素。</li>
    <li><code>event.target as HTMLInputElement</code> 表示把事件目标当作输入框元素。</li>
    <li>断言之后,就可以访问输入框的 <code>value</code> 属性。</li>
  </ol>

  <p>
    在 Vue3 中,也会看到类似写法:
  </p>

  <pre><code>@input="inputValue = ($event.target as HTMLInputElement).value"</code></pre>

  <p>
    这句代码的含义是:
    当输入框发生输入事件时,把事件目标当作输入框元素,
    然后读取它的 <code>value</code></p>

  <hr>

  <h2>六、类型断言和类型标注的区别</h2>

  <p>
    类型标注和类型断言看起来都和类型有关,
    但它们的含义不同。
  </p>

  <p>
    类型标注用于声明变量、参数或返回值应该是什么类型。
  </p>

  <pre><code>let username: string = "jack";

function sayHello(name: string): void {
  console.log("你好," + name);
}</code></pre>

  <p>
    类型断言用于告诉 TypeScript:
    某个值现在可以当作某种类型来看待。
  </p>

  <pre><code>const element = document.querySelector("#username");

const input = element as HTMLInputElement;</code></pre>

  <p>
    可以这样区分:
  </p>

  <ol>
    <li>类型标注:提前规定一个变量或参数应该是什么类型。</li>
    <li>类型断言:在某个具体位置告诉 TypeScript,把这个值当作某个类型来看。</li>
  </ol>

  <p>
    简单来说:
  </p>

  <pre><code>let age: number = 18;              // 类型标注
const input = element as HTMLInputElement; // 类型断言</code></pre>

  <hr>

  <h2>七、类型断言要谨慎使用</h2>

  <p>
    类型断言很有用,但不能乱用。
    因为类型断言相当于告诉 TypeScript:
    “相信我,这个值就是这个类型。”
  </p>

  <p>
    如果断言错误,TypeScript 可能不会继续提示问题,
    但代码运行时仍然可能出错。
  </p>

  <pre><code>const element = document.querySelector("#title");

const input = element as HTMLInputElement;

console.log(input.value);</code></pre>

  <p>
    如果页面中 <code>#title</code> 实际上是一个 <code>h1</code> 标题元素,
    那么把它断言为输入框就不合适。
  </p>

  <p>
    因为 <code>h1</code> 元素没有普通输入框那样的 <code>value</code> 属性。
  </p>

  <p>
    所以使用类型断言时,要遵守一个原则:
    <strong>只有在你确实知道这个值的具体类型时,才使用类型断言。</strong>
  </p>

  <hr>

  <h2>八、类型断言不能随意断言成完全无关的类型</h2>

  <p>
    TypeScript 不允许把明显不相关的类型随意断言。
  </p>

  <pre><code>let age = 18;

let username = age as string;</code></pre>

  <p>
    上面代码通常会报错。
    因为 <code>number</code><code>string</code> 之间没有足够的关联。
  </p>

  <p>
    这也提醒我们:
    类型断言不是随便把一个类型“改成”另一个类型。
  </p>

  <p>
    如果确实要把数字转换成字符串,应该使用真正的转换方法。
  </p>

  <pre><code>let age = 18;

let username = String(age);

console.log(username);</code></pre>

  <p>
    这里的 <code>String(age)</code> 才是运行时的字符串转换。
  </p>

  <hr>

  <h2>九、类型断言的常见场景</h2>

  <p>
    当前阶段只需要掌握类型断言的几个常见场景。
  </p>

  <h3>场景一:获取输入框元素</h3>

  <pre><code>const element = document.querySelector("#username");

if (element !== null) {
  const input = element as HTMLInputElement;
  console.log(input.value);
}</code></pre>

  <p>
    这种场景中,类型断言用于告诉 TypeScript:
    获取到的元素是输入框。
  </p>

  <h3>场景二:处理事件目标</h3>

  <pre><code>function handleInput(event: Event): void {
  const input = event.target as HTMLInputElement;
  console.log(input.value);
}</code></pre>

  <p>
    这种场景中,类型断言用于告诉 TypeScript:
    事件目标是输入框元素。
  </p>

  <h3>场景三:处理 unknown 类型</h3>

  <pre><code>let value: unknown = "hello";

let message = value as string;

console.log(message.length);</code></pre>

  <p>
    这种场景中,类型断言用于告诉 TypeScript:
    <code>value</code> 当前可以当作字符串使用。
  </p>

  <hr>

  <h2>十、常见错误写法</h2>

  <p>
    下面列出一些初学者容易写错的地方。
  </p>

  <h3>错误一:把类型断言当成类型转换</h3>

  <pre><code>let value: unknown = "100";

let num = value as number;

console.log(num + 1);</code></pre>

  <p>
    错误原因:
    <code>value as number</code> 不会把字符串 <code>"100"</code> 转换成数字。
    它只是类型断言。
  </p>

  <p>
    正确写法:
  </p>

  <pre><code>let value = "100";

let num = Number(value);

console.log(num + 1);</code></pre>

  <h3>错误二:没有确认元素类型就随意断言</h3>

  <pre><code>const title = document.querySelector("#title");

const input = title as HTMLInputElement;

console.log(input.value);</code></pre>

  <p>
    错误原因:
    如果 <code>#title</code> 实际上是标题元素,
    把它断言为输入框就不合适。
  </p>

  <p>
    更合理的做法:
  </p>

  <pre><code>const element = document.querySelector("#username");

if (element !== null) {
  const input = element as HTMLInputElement;
  console.log(input.value);
}</code></pre>

  <h3>错误三:忘记处理 null</h3>

  <pre><code>const element = document.querySelector("#username");

const input = element as HTMLInputElement;

console.log(input.value);</code></pre>

  <p>
    如果页面中不存在 <code>#username</code> 元素,
    <code>document.querySelector</code> 会返回 <code>null</code>。
    这时继续访问 <code>value</code> 就可能出错。
  </p>

  <p>
    更安全的写法:
  </p>

  <pre><code>const element = document.querySelector("#username");

if (element !== null) {
  const input = element as HTMLInputElement;
  console.log(input.value);
}</code></pre>

  <hr>

  <h2>十一、完整小示例</h2>

  <p>
    下面通过一个输入框案例,综合演示类型断言的基本用法。
  </p>

  <pre><code>// 假设页面中有如下输入框:
// &lt;input id="username" type="text" value="jack"&gt;

// 获取页面元素
const element = document.querySelector("#username");

// 先判断元素是否存在
if (element !== null) {
  // 把普通元素断言为输入框元素
  const input = element as HTMLInputElement;

  // 读取输入框的值
  console.log("用户名:" + input.value);
}

// 事件处理函数
function handleInput(event: Event): void {
  // 把事件目标断言为输入框元素
  const input = event.target as HTMLInputElement;

  console.log("当前输入内容:" + input.value);
}

// unknown 类型示例
let value: unknown = "hello TypeScript";

// 把 unknown 断言为 string
let message = value as string;

console.log("字符串长度:" + message.length);

// 错误示例
// let text: unknown = "100";
// let num = text as number;
// console.log(num + 1); // 类型断言不会把字符串转换成数字</code></pre>

  <p>
    这个案例中:
  </p>

  <ol>
    <li>通过 <code>document.querySelector</code> 获取页面元素。</li>
    <li>先判断元素是否存在,再进行类型断言。</li>
    <li>使用 <code>element as HTMLInputElement</code> 把元素当作输入框元素。</li>
    <li>使用 <code>event.target as HTMLInputElement</code> 处理输入框事件。</li>
    <li>使用 <code>value as string</code><code>unknown</code> 值当作字符串处理。</li>
    <li>类型断言不会改变运行时数据本身。</li>
  </ol>

  <hr>

  <h2>十二、本节总结</h2>

  <p>
    本节学习了 TypeScript 类型断言。
  </p>

  <ol>
    <li>类型断言用于告诉 TypeScript 某个值的具体类型。</li>
    <li>类型断言推荐使用 <code>as</code> 语法。</li>
    <li>基本写法是:<code>值 as 类型</code></li>
    <li>类型断言不是类型转换。</li>
    <li>类型断言不会改变运行时的数据本身。</li>
    <li>类型断言常用于 DOM 元素。</li>
    <li>类型断言常用于事件对象。</li>
    <li>类型断言可以用于处理 <code>unknown</code> 类型。</li>
    <li>使用类型断言前,应尽量确认真实类型。</li>
    <li>获取 DOM 元素时,要注意元素可能为 <code>null</code></li>
    <li>后续 Vue3 中常见的 <code>($event.target as HTMLInputElement).value</code> 就是类型断言。</li>
  </ol>


</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谷哥的小弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值