版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址: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><input id="username" type="text" value="jack"></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>// 假设页面中有如下输入框:
// <input id="username" type="text" value="jack">
// 获取页面元素
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>
3247

被折叠的 条评论
为什么被折叠?



