TypeScript 学习笔记(八):类型断言

前言

在上一篇文章TypeScript 学习笔记(七):泛型中我们学习了TS中的函数类型,本篇文章我们主要了解TS中的类型断言

如果你也和我一样在为大厂冲刺的话,欢迎添加我的微信lx3122178991,这里有一群小伙伴有着和你同样的目标,欢迎来一起讨论,一同进步。

类型断言是什么

TS对于没有进行类型声明的值进行类型推断,但是很多时候得到的结果并不是想要的结果。就比如下面这个例子。

TS 复制代码
type T = 'a'|'b'|'c';
let foo = 'a';

let bar:T = foo; // 报错

在这个例子中,TS推断变量foo的类型是string,但是变量bar的类型是'a'|'b'|'c',前者是后者的父类型,父类型不能赋值给子类型。所以就最后一行报错了。

为了解决这一个问题,TS提供了类型断言 这样一种手段,允许在代码中"断言"某个值的类型,告诉编译器此处的值是什么类型。TS一旦发现存在类型断言,就不再对该值进行类型推断,而是直接采用断言给出的类型。

所以上面的例子可以改成这样。

TS 复制代码
type T = 'a'|'b'|'c';

let foo = 'a';
let bar:T = foo as T; // 正确

最后一行的foo as T表示告诉编译器,变量foo的类型断言为T,所以这一行不再需要类型推断了,编译器直接把foo的类型当作T,就不会报错了。

类型断言的语法

类型断言有两种语法。

TS 复制代码
// 语法一:<类型>值
<Type>value

// 语法二:值 as 类型
value as Type

上面两种语法是等价的,value表示值,Type表示类型。早期只有语法一,后来因为TS开始支持ReactJSX语法,为了避免两者冲突,就引入了语法二。

类型断言的使用条件

类型断言并是把某个值断言为任意类型。 下面的例子中,变量n是数值,无法把它断言成字符串,TS就会报错。

TS 复制代码
const n = 1;
const m:string = n as string; // 报错

类型断言的使用前提是,值的实际类型与断言的类型必须满足一个条件。 valueType的子类型,或者Typevalue的子类型。

TS 复制代码
value as Type

但是,如果真的要断言成一个完全无关的类型,也是可以做到的。

那就是连续进行两次类型断言,先断言成unknown类型或any类型,然后再断言为目标类型。因为any类型和unknown类型是所有其他类型的父类型,所以可以作为两种完全无关的类型的中介。

TS 复制代码
value as unknown as Type

as const 断言

TS中,如果没有声明变量类型,let 命令声明的变量,会被类型推断为TS内置的基本类型之一;const 命令声明的变量,则被推断为值类型常量。

TS 复制代码
// 类型推断为基本类型 string
let s1 = 'JavaScript';

// 类型推断为字符串 "JavaScript"
const s2 = 'JavaScript';

有些时候,let 变量会出现一些意想不到的报错,变更成 const 变量就能消除报错。

TS 复制代码
let s = 'JavaScript';

type Lang =
  |'JavaScript'
  |'TypeScript'
  |'Python';

function setLang(language:Lang) {
  /* ... */
}

setLang(s); // 报错

在上面例子中,函数setLang()的参数language类型是Lang,这是一个联合类型。但是,传入的字符串s的类型被推断为string,属于Lang的父类型。父类型不能替代子类型,导致报错。

解决方法就是把 let 命令改成 const 命令。

TS 复制代码
const s = 'JavaScript';

这样的话,变量s的类型就是值类型JavaScript,它是联合类型Lang的子类型,传入函数setLang()就不会报错。

除了改成const 命令之外,TS提供了一种特殊的类型断言as const,用于告诉编译器,推断类型时,可以将这个值推断为常量。

TS 复制代码
let s = 'JavaScript' as const;
setLang(s);  // 正确

注意:使用了as const断言以后,let 变量就不能再改变值了。

TS 复制代码
let s = 'JavaScript' as const;
s = 'Python'; // 报错
相关推荐
李明卫杭州3 分钟前
CSS BFC 完全指南:从原理到实战,彻底搞懂这个"结界"
前端
Momo__4 分钟前
MDN MCP Server——Mozilla 把 Web 文档接进 AI Agent,从此 LLM 不再瞎编 API
前端·ai编程·mcp
妙码生花4 分钟前
现代前端的极致性能 icon 加载方案(死磕成功版)
前端·vue.js·typescript
掘金者阿豪1 小时前
把业务数据变成共享仪表盘:Metabase可视化与远程访问实践
前端·后端
kyriewen1 小时前
折腾了半年 AI 编程工作流,最后发现效率瓶颈是桌上那块屏幕
前端·javascript·ai编程
蜗牛前端2 小时前
codex 全流程开发上线的高颜值礼簿小程序
前端·微信小程序
大龄秃头程序员2 小时前
我在图文流 App 里落地双层缓存、弱网降级与 OOM 治理
前端
老王以为2 小时前
React Renderer 分离的多平台架构
前端·react native·react.js
hunterandroid3 小时前
Kotlin Coroutines 与 Flow:让异步任务更清晰
前端
Bigger3 小时前
从零搭建 AI 代码审查服务:一份前端也能看懂的 Python 学习笔记
前端·ci/cd·ai编程