我们知道,ts是强类型语言,如果想要有更好的语法提示和类型检测,我们就需要缩小变量的类型范围。下面这些方法可以帮助我们缩小变量范围。
类型断言,类型转换
就是通过as
关键字来将变量强制推断为某种类型。就是绕过ts编译检查,类型断言就是对编译器说:我就是这个类型,无需检查。注意这种转换变量类型和转换的类型必须有重叠的类型,否则是不被允许的。
function foo(a: number | string) {
a = (a as number) + 1 // 将a强制推断为number类型
return a
}
console.log(foo("2")) // “21”
还有就是如果项目中有些类型编译时报错,我们可以强制断言成any
类型。(在开发中在座的各位是不是都是这么干的。🫣)
let symid = Symbol()
const user = {
[symid]: 1,
username: "zh"
}
let username = "username"
console.log("username:", user[username as any]) // zh
类型转换和类型断言有相同的作用,就是将当前变量强制推断为某个类型,而不让编译器在进行检测。注意这种转换变量类型和转换的类型必须有重叠的类型,否则是不被允许的。
// const num = <number>"3" // error
const num = <number><any>"3" // 字符串和数字类型没有重叠部分,所以需要先将string转为any或者unknown才可以转为number
类型守卫
在语句的块级作用域(if语句内或条目运算符表达式内)缩小变量的一种类型推断的行为。
TS 条件语句中遇到下列条件关键字时,会在语句的块级作用域内缩小变量的类型,这种类型推断的行为称作类型守卫(Type Guard)。类型守卫可以帮助我们在块级作用域中获得更为需要的精确变量类型。
- 实例判断:
instanceof
- 属性或者方法判断:
in
- 类型判断:
typeof
- 字面量相等判断:
==, ===, !==, !=
instanceof
这个一般用在类中,类似于其他面向对象语言中的多态。例如在方法接收一个父类类型的变量时,我们在方法体中可以通过instanceof
来缩小该两边的类型范围,让我们可以有更好的语法提示等等。
class Person {
constructor(public name: string, public age: number) {
}
say() {
}
}
class Child extends Person {
constructor(public name: string, public age: number, public playName: number) {
super(name, age)
}
play() {
}
}
class Dog extends Person {
constructor(public name: string, public age: number, public sleepName: number) {
super(name, age)
}
sleep() {
}
}
class Customer {
constructor(public name: string) {
}
buy(object: Person) {
if(object instanceof Child) { // Child
object.play()
}else if(object instanceof Dog){ // Dog
object.sleep()
}
}
}
in
主要是通过判断该对象中是否有指定属性和方法,来确定对象的类型。
class Customer {
constructor(public name: string) {
}
buy(object: Person) { // 这里定义父类类型,使用in操作符并不能推断出具体的类型
if("play" in object) {
object.play() // error
}else if("sleep" in object){
object.sleep() // error
}
}
buy(object: Child | Dog) { // 这里的object类型还不能直接写成Person,否则 in 操作符不能正确推断
if("play" in object) {
object.play()
}else if("sleep" in object){
object.sleep()
}
}
}
typeof
他主要就是来缩小一些联合的基本数据类型变量的类型范围了。
function bar(a: number | string) {
if(typeof a === "number") {
a.toFixed()
}else {
a.replace("", "")
}
}
自定义守卫
如果我们代码中有多处都需要缩小变量类型,我们就可以自定义一个守卫供我们使用,来简化代码。
function 函数名(形参: 参数类型,大多为any): 形参 is A类型 {
return true / false
}
如果我们不使用自定义守卫,而是单独封装一个方法用于判断,那么ts只是把它当做一个boolean,并不会缩小变量类型范围。
class Customer {
constructor(public name: string) {
}
buy(object: Person) {
if(isChild(object)) { // 这里只会被看作是一个boolean,并不会将object看做为Child类型
object.play() // error
}
}
}
function isChild(object: Person): boolean {
return object instanceof Child
}
所以我们可以使用自定义守卫。
class Customer {
constructor(public name: string) {
}
buy(object: Person) {
if(isChild(object)) {
object.play()
}
}
}
// function isChild(object: Person): boolean {
// return object instanceof Child
// }
function isChild(object: Person) { // 这里不指定返回值类型,他也会推断出为 object is Child
return object instanceof Child
}
往期年度总结
往期文章
- 经常使用ts的你,知道这些内容?
- 你有了解过原生css的scope?
- 现在比较常用的移动端调试你知道哪些?
- 众多跨标签页通信方式,你知道哪些?(二)
- 众多跨标签页通信方式,你知道哪些?
- 反调试吗?如何监听devtools的打开与关闭
- 因为原生,选择一家公司(前端如何防笔试作弊)
- 结合开发,带你熟悉package.json与tsconfig.json配置
- 如何优雅的在项目中使用echarts
- 如何优雅的做项目国际化
- 近三个月的排错,原来的憧憬消失喽
- 带你从0开始了解vue3核心(运行时)
- 带你从0开始了解vue3核心(computed, watch)
- 带你从0开始了解vue3核心(响应式)
- 3w+字的后台管理通用功能解决方案送给你
- 入职之前,狂补技术,4w字的前端技术解决方案送给你(vue3 + vite )
专栏文章
结语
本篇文章到此就结束了,欢迎在评论区交流。
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论, 支持一下博主~