TypeScript类型断言VS类型守卫示例详解

 更新时间:2022年11月14日 10:50:39   作者:何遇er  
这篇文章主要为大家介绍了TypeScript类型断言VS类型守卫示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

类型断言

类型断言有两种写法,分别为value as Type<Type>value,它让 TypeScript 编译器将 value 当作 Type 类型。类型断言是一个编译时特性,不进行类型转换,因此不会影响变量在运行时的数据类型。如果某变量是 any 类型,但现在你知道它确切的数据类型,使用类型断言能让 IDE 有代码提示的能力,也能让 TypeScript 编译器进行类型检查。

类型断言的用法如下:

const age: any = 23.44;
const user: any = {age: 2}
// age 的 原始数据类型是 any ,在这里将它断言为 number 类型
(age as number).toFixed(0);
(<number>age).toFixed(0);
// 将user断言为非null和非undefined
user!.age

除非确切的知道变量的数据类型,否则不要使用类型断言,这是因为类型断言会让 TypeScript 编译器将变量当做指定的类型,而不管它实际的类型,在程序运行时可能有类型错误。

类型守卫

类型守卫的工作是将数据类型收窄,比如,变量 age 的数据类型可能是 string 也可能是 number,现在要将 age 收窄为 string 类型,类型守卫能实现它。总体而言,有4种方式让数据类型收窄。

使用 in 关键字

如果某变量的数据类型是联合类型,并且该变量存在一个属性绝对不会出现在联合类型的其他成员类型上,那么可以使用 in 关键字将类型收窄。用法如下:

function printType(value: User | Student) {
    // grade 只存在 Student 类型上
if ('grade' in value) { 
        // 在 if 块中,value 的数据类型被收窄为 Student 类型
        console.log('它是 Student 类型',value.name + ':' + value.grade)
    } else {
	// 在 else 块中,value 的数据类型被收窄为 User 类型
        console.log('它是 User 类型',value.name)
    }
}

使用 instanceof 关键字

用 in 关键字收窄数据类型有局限性,必须有一个独特的属性作为判别符,否则,不能用 in 关键字收窄。如果正在处理的变量是类的实例,那么可以用 instanceof 关键字收窄数据类型。用法如下:

function printInfo(value: Staff | Student) {
    if (value instanceof Staff) {
        // 在 if 块中,value 的数据类型被收窄为 Staff 类型
        console.log('它是 Staff 类型')
    } else {
        // 在 else 块中,value 的数据类型被收窄为 Student 类型
        console.log('它是 Student 类型')
    }
}

使用 typeof 关键字

使用 typeof 能得到值的数据类型,如果变量的类型为基本类型,如:string、number 等,使用 typeof 也能将数据类型收窄。用法如下:

function printType(value: string | number) {
    if (typeof value === 'string') {
        // value 的类型被收窄为 string
        console.log('value 是 string 类型')
    } else {
        // value 的类型被收窄为 number
        console.log('value 是 number 类型')
    }
}
// 用对象上某个字段收窄数据类型
//如果 User 类型的 name 字段为 string 类型,Student 类型的 name 字段为 number 类型
function printObjType(obj: User | Student) {
    if (typeof obj.name === 'string') {
        // value 的类型被收窄为 User
    } else {
        // value 的类型被收窄为 Student
    }
}

自定义类型守卫

用 in、instanceof 和 typeof 关键字收窄数据类型语法很简单,但都有各自的局限性。如果它们不能当作类型守卫,那么能使用 is 关键字自定义类型守卫,写法为:parameter is Type,这种写法被称为类型谓词,要将它放在函数返回值的位置。

类型谓词所在的函数被称为类型谓词函数,它的返回值必须为 boolean 类型。类型谓词中的 Type可以是任意合法的 TypeScript 数据类型,parameter 可以是函数的参数也能是 this 关键字。

当类型谓词中的 parameter 是函数的参数,用法如下:

function predicateStudent(value: Student | User): value is Student {
    return typeof (value as any).garde === 'number'
}
function printObjType(obj: User | Student) {
    if (predicateStudent(obj)) {
        // obj的类型被收窄为 Student
    } else {
        // value 的类型被收窄为 User
    }
}

上述代码中的 predicateStudent 是类型谓词函数,如果它返回 true,那么参数的数据类型被收窄为 Student。

当类型谓词中的 parameter 是 this 关键字,这种用法通常出现在类的方法中,用法如下:

abstract class User {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    isStudent(): this is Student {
        return this instanceof Student;
    }
    isStaff(): this is Staff {
        return this instanceof Staff; 
    }
}
class Student extends User{
    grade: number;
    constructor(name: string, grade: number) {
        super(name)
        this.grade = grade
    }
}
class Staff extends User {
    salary: number;
    constructor(name: string, salary: number) {
        super(name)
        this.salary = salary
    }
}
function printObjType(obj: User) {
    if (obj.isStaff()) {
        // obj 的类型被收窄为 Staff
    } else if (obj.isStudent()){
        // obj 的类型被收窄为 Student
    }
}

上述代码中的 User 是抽象类,不能被实例化,Staff 和 Student 都继承自 User。实例方法 isStaff 用于将类型收窄为 Staff,实例方法 isStudent 用于将类型收窄为 Student。

总结

在项目中,如果某变量有多种数据类型,不建议使用类型断言将它断言成特定的类型,而是使用类型守卫根据实际情况将类型收窄,然后按不同的类型分别处理。类型守卫能让应用程序的数据类型更安全,不至于程序在编译阶段不报错,但在运行阶段报错。

以上就是TypeScript类型断言VS类型守卫示例详解的详细内容,更多关于TypeScript类型断言类型守卫的资料请关注脚本之家其它相关文章!

相关文章

  • Bootstrap table简单使用总结

    Bootstrap table简单使用总结

    这篇文章主要为大家总结了Bootstrap table的简单使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • js实现手表表盘时钟与圆周运动

    js实现手表表盘时钟与圆周运动

    这篇文章主要为大家详细介绍了js实现手表表盘时钟与圆周运动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • layui table 列宽百分比显示的实现方法

    layui table 列宽百分比显示的实现方法

    今天小编就为大家分享一篇layui table 列宽百分比显示的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • 使用Javascript和DOM Interfaces来处理HTML

    使用Javascript和DOM Interfaces来处理HTML

    使用Javascript和DOM Interfaces来处理HTML...
    2006-10-10
  • js实现base64文件的处理以及下载方法

    js实现base64文件的处理以及下载方法

    Base64是一种将二进制数据编码为ASCII字符的编码方式,这篇文章主要给大家介绍了关于js实现base64文件的处理以及下载的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • javascript遍历控件实例详细解析

    javascript遍历控件实例详细解析

    这篇文章详细解析了javascript遍历控件实例,有需要的朋友可以参考一下
    2014-01-01
  • js获取当前年月日时分秒的方法实例(new Date()/moment.js)

    js获取当前年月日时分秒的方法实例(new Date()/moment.js)

    JavaScript是一种流行的编程语言,它可以用来获取当前年月日,这篇文章主要给大家介绍了关于js获取当前年月日时分秒的相关资料,分别使用的是new Date()/moment.js,需要的朋友可以参考下
    2024-07-07
  • javascript中巧用“闭包”实现程序的暂停执行功能

    javascript中巧用“闭包”实现程序的暂停执行功能

    javascript中巧用“闭包”实现程序的暂停执行功能...
    2007-04-04
  • 原生JavaScript实现Ajax异步请求

    原生JavaScript实现Ajax异步请求

    ajax现在是一种非常流行的技术,现在虽然可以利用JQuery或者一些第三方插件甚至微软提供的一些控件可以方面的实现ajax功能,但是明白其原理也是非常重要的,下面是来使用纯javascript实现获取服务器端的功能来展示如何使用纯javascript实现ajax功能,以弄清其原理.
    2017-11-11
  • 理解javascript封装

    理解javascript封装

    这篇文章主要帮助大家理解学习javascript封装,通过封装可以强制实施信息隐藏,本文为大家分析了封装的利弊,感兴趣的小伙伴们可以参考一下
    2016-02-02

最新评论