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类型断言类型守卫的资料请关注脚本之家其它相关文章!

相关文章

  • 前端实现文本超出指定行数显示"展开"和"收起"效果详细步骤

    前端实现文本超出指定行数显示"展开"和"收起"效果详细步骤

    本文介绍如何使用JavaScript原生代码实现文本折叠展开效果,并提供方法指导如何在Vue或React等框架中修改实现,详细介绍了创建整体框架、设置样式及利用JS控制元素的步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • js实现鼠标拖拽多选功能示例

    js实现鼠标拖拽多选功能示例

    本篇文章主要介绍了js实现鼠标拖拽多选功能示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • JavaScript 在线压缩和格式化收藏

    JavaScript 在线压缩和格式化收藏

    国外人写的在线压缩和格式化工具这两套程序都是用纯 JavaScript 写的,可以下载下来离线使用,很方便。
    2009-01-01
  • JavaScript实现的微信二维码图片生成器的示例

    JavaScript实现的微信二维码图片生成器的示例

    二维码分享功能大多是由后端实现的,对服务器的负载较重,这里有一个前端实现的版本,本文介绍了JavaScript实现的微信二维码图片生成器的示例,有需要的可以了解一下。
    2016-10-10
  • WebApi+Bootstrap+KnockoutJs打造单页面程序

    WebApi+Bootstrap+KnockoutJs打造单页面程序

    这篇文章主要介绍了WebApi+Bootstrap+KnockoutJs打造单页面程序的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • JavaScript闭包中难点深入分析

    JavaScript闭包中难点深入分析

    闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,下面这篇文章主要给大家介绍了关于JavaScript闭包函数的相关资料,需要的朋友可以参考下
    2022-11-11
  • JavaScript实现简单的Markdown语法解析器

    JavaScript实现简单的Markdown语法解析器

    Markdown 是一种轻量级标记语言, 它允许人们使用易读易写的纯文本格式编写文档,然后转换成有效的 XHTML(或者HTML)文档。本文将利用JavaScript实现简单的Markdown语法解析器,感兴趣的可以了解一下
    2023-03-03
  • 用javascript作一个通用向导说明

    用javascript作一个通用向导说明

    向导可以让你的网站用户快速上手使用你的web应用,提高网站的吸引力。向导一般分为好几个步骤,每个步骤收集一些数据,并且支持退回功能,所有步骤完成后可以得到每一步的收集结果。这里给大家展示一种比较通用,灵活且简单的向导框架。
    2011-08-08
  • 简单了解JavaScript中的new Function

    简单了解JavaScript中的new Function

    这篇文章主要介绍了简单了解JavaScript中的new Function,文章通过围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • JS利用prototype给类添加方法操作详解

    JS利用prototype给类添加方法操作详解

    这篇文章主要介绍了JS利用prototype给类添加方法操作,结合实例形式分析了javascript使用prototype实现给类添加方法的相关操作技巧,需要的朋友可以参考下
    2019-06-06

最新评论