TypeScript 非空断言

这篇具有很好参考价值的文章主要介绍了TypeScript 非空断言。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

TypeScript 非空断言

发布于 2020-04-08 15:20:15

17.5K0

举报

一、非空断言有啥用

介绍非空断言前,先来看个示例:

function sayHello(name: string | undefined) {
  let sname: string = name; // Error
}

对于以上代码,TypeScript 编译器会提示一下错误信息:

Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.

要解决上述问题,我们可以简单加个条件判断:

function sayHello(name: string | undefined) {
  let sname: string;
  if (name) {
    sname = name;
  }
}

使用这种方案,问题是解决了。但有没有更简单的方式呢?答案是有的,就是使用 TypeScript 2.0 提供的非空断言操作符:

function sayHello(name: string | undefined) {
  let sname: string = name!;
}

二、非空断言操作符简介

在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非undefined 类型。具体而言,x! 将从 x 值域中排除 nullundefined

下面我们来介绍一下非空断言操作符的一些使用场景和注意事项。

2.1 忽略 undefined 和 null 类型
function myFunc(maybeString: string | undefined | null) {
  // Type 'string | null | undefined' is not assignable to type 'string'.
  // Type 'undefined' is not assignable to type 'string'. 
  const onlyString: string = maybeString; // Error
  const ignoreUndefinedAndNull: string = maybeString!; // Ok
}
2.2 调用函数时忽略 undefined 类型
type NumGenerator = () => number;

function myFunc(numGenerator: NumGenerator | undefined) {
   // Object is possibly 'undefined'. 
   // Cannot invoke an object which is possibly 'undefined'.
   const num1 = numGenerator(); // Error
   const num2 = numGenerator!(); //OK
}
2.3 使用非空断言操作符的注意事项

因为 ! 非空断言操作符会从编译生成的 JavaScript 代码中移除,所以在实际使用的过程中,要特别注意。

下面我们来举两个简单的示例:

示例一

const a: number | undefined = undefined;
const b: number = a!;
console.log(b);

以上 TS 代码会编译生成以下 ES5 代码:

"use strict";
const a = undefined;
const b = a;
console.log(b);

虽然在 TS 代码中,我们使用了非空断言,使得 const b: number = a!; 语句可以通过 TypeScript 类型检查器的检查。但在生成的 ES5 代码中,! 非空断言操作符被移除了,所以在浏览器中执行以上代码,在控制台会输出 undefined

示例二

type NumGenerator = () => number;

function myFunc(numGenerator: NumGenerator | undefined) {
   const num1 = numGenerator!();
}

// Uncaught TypeError: numGenerator is not a function
myFunc(undefined); // Error

以上 TS 代码会编译生成以下 ES5 代码:

"use strict";
function myFunc(numGenerator) {
  var num1 = numGenerator();
}

// Uncaught TypeError: numGenerator is not a function
myFunc(undefined); // Error

若在浏览器中运行以上代码,在控制台会输出以下错误信息:

Uncaught TypeError: numGenerator is not a function
    at myFunc (eval at <anonymous> (main-3.js:1239), <anonymous>:3:16)
    at eval (eval at <anonymous> (main-3.js:1239), <anonymous>:6:1)
    at main-3.js:1239

很明显在运行时,undefined 并不是函数对象,所以就不能正常调用。

需要注意的是,非空断言操作符仅在启用 strictNullChecks 标志的时候才生效。当关闭该标志时,编译器不会检查 undefined 类型和 null 类型的赋值。

三、非空断言操作符使用示例

在以下示例中,首先我们使用 TypeScript 类型别名定义了一个 ListNode 类型,用于表示链表节点。该类型包含 datanext 两个属性,分别表示当前节点的值和下个节点。之后,我们还定义了以下两个函数:

  • addNext(node: ListNode):用于添加下一个节点;
  • setNextValue(node: ListNode, value: number):用于设置下一个节点的值。
type ListNode = { data: number; next?: ListNode; };

function addNext(node: ListNode) {
  if (node.next === undefined) {
    node.next = {data: 0};
  }
}

function setNextValue(node: ListNode, value: number) {
  addNext(node);
  // (property) next?: ListNode | undefined
  // Object is possibly 'undefined'.(2532)
  node.next.data = value; // Error
}

对于以上代码尽管我们知道在调用 addNext 方法后,node.next 属性会被定义,但 TypeScript 在 node.next.data = value 这行代码中并不能推断出这些。这时候我们可以使用非空断言运算符 ! 来断言 node.next 并不是 undefined,并且使编译器警告无效:

function setNextValue(node: ListNode, value: number) {
  addNext(node);
  node.next!.data = value;
}

接着我们继续看一个示例,假设你有一个表示 AJAX 请求过程的 UI 状态。它要么处于初始状态(initial),要么处于挂起状态(pending),要么处于完成状态(complete),要么处于错误状态(error)。只有在完成状态下才有响应,否则为 null。

type AjaxState<T> = {
  state: 'initial' | 'pending' | 'complete' | 'error';
  response: T | null;
}

function getAjaxState( ajaxState: AjaxState<number[]> ) {
  if (ajaxState.state === 'complete') {
    // (property) response: number[] | null
    // Object is possibly 'null'.(2531)
    console.log(ajaxState.response.length); // Error
  }
}

虽然我们知道当请求的状态为 complete 时,响应对象不会为 null,但 TypeScript 并无法感知这些,所以我们还需要使用非空断言 ajaxState.response!.length 来忽略空值并使编译器警告无效。对于这种场景,其实有一个更好的解决方案,即使用可辨识联合:

type AjaxState<T> = 
  { state: 'initial'|'pending'|'error', response: null } |
  { state: 'complete', response: T };

function getAjaxState( ajaxState: AjaxState<number[]> ) {
  if (ajaxState.state === 'complete') {
    console.log(ajaxState.response.length);
  }
}

通过引入可辨识联合类型,我们把为 null 和非 null 的响应完美的区分开来,还避免了再次使用非空断言,此外还大大提高了程序的可读性。在 TypeScript 实际项目的开发过程中,除了使用非空断言(!)之外,读者还可以使用 TypeScript 3.7 版本中新引入的可选链运算符(?.)和空值合并运算符(??)来提高程序的可读性。文章来源地址https://www.toymoban.com/news/detail-645717.html

到了这里,关于TypeScript 非空断言的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • TypeScript -类型断言的简单理解

    类型断言 : 是手动的给某个变量 指定类型,从而可以方便操作该类型的属性和方法。 方式一 : 变量名 as 类型 方式二 :类型 变量名 注意 : 1、类型断言只是为了方便明确变量的类型,而不是将变量的类型进行改变!!! 2、因此,类型断言在使用的时候,建议 在我们已

    2024年02月08日
    浏览(41)
  • TypeScript基础知识:类型断言

            在 TypeScript 中,类型断言是一种强制将一个值视为特定类型的方式。它允许开发人员在编译时指定变量的类型,从而获得更好的类型检查和代码提示。本文将深入探讨 TypeScript 中的类型断言,并提供丰富的示例代码帮助读者更好地理解和应用这一特性。       

    2024年01月25日
    浏览(44)
  • TypeScript 联合类型,类型推断,类型断言

    取值可以为多种类型中的一个 当变量需要调用某属性的时候,有不确定当前的类型是什么,可以使用类型断言; 类型断言的两种方式: 1,类型 变量名; 2,值 as 类型; 没有明确的指定类型的情况下推断出一个类型;

    2024年02月15日
    浏览(39)
  • 【TypeScript】类型断言-类型的声明和转换(五)

    一、简介 TypeScript 断言是指在编写代码时,开发者能够告诉编译器某个值的具体类型,从而可以在编译阶段强制类型检查。 这其实在某些强类型语言中,类似于强制类型转换的操作。 类型断言有两种形式实现: 尖括号语法 as语法 二、断言形式 2.1 尖括号语法 尖括号语法:开

    2024年02月13日
    浏览(47)
  • 服务端使用ASP.NET Core SignalR与Vue3(TypeScript与JavaScript)前端建立通信(以进度条为例)

    1. ASP.NET Core           ASP.NET Core 是一个跨平台、高性能及开源的框架,用于生成基于云且连接互联网的新式应用程式。 官方文档:ASP.NET documentation | Microsoft Learn  2.  ASP.NET Core SignalR         ASP.NET Core SignalR 是开源库,用于服务端与客户端建立实时通信,可以自动管理连接

    2024年02月06日
    浏览(48)
  • TypeScript 在前端开发中的应用实践

    TypeScript 已经成为前端开发领域越来越多开发者的首选工具。它是一种静态类型的超集,由 Microsoft 推出,为开发者提供了强大的静态类型检查、面向对象编程和模块化开发的特性,解决了 JavaScript 的动态类型特性带来的一些问题。 在本篇博文中,我们将深入探讨 TypeScript 在

    2024年02月15日
    浏览(37)
  • 前端2023最全面试题(javaScript、typeScript、vue2、vue3、html、css、uniapp、webpack、vite、react)

    答案:JavaScript中的闭包是一种函数,它有权访问其词法环境的变量和其它函数。这意味着,即使其包含它的函数已经执行完毕,其词法环境仍然存在,因此可以访问其作用域内的变量。 答案:回调函数是在某个特定事件之后执行的函数。在JavaScript中,通常使用回调函数来处

    2024年02月06日
    浏览(65)
  • TypeScript在前端开发中的重要性

    近年来, TypeScript 在前端开发中的重要性逐渐得到认可。作为一种静态类型的 JavaScript 的超集, TypeScript 通过引入静态类型、接口、类等特性,为前端开发带来了许多优势。本文将探讨 TypeScript 在前端开发中的重要性,并通过代码论证其价值。 首先, TypeScript 通过引入静态类

    2024年02月11日
    浏览(41)
  • 【TypeScript】TS类型断言-类型的声明和转换(五)

    🐱个人主页: 不叫猫先生 🙋‍♂️作者简介:前端领域新星创作者、华为云享专家、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫系列专栏:vue3从入门到精通、TypeScript从入门到实践 📝个人签名:不破不立 📢资料领取:前端进阶资料以

    2024年02月22日
    浏览(39)
  • TypeScript 学习笔记(一):基本类型、交叉类型、联合类型、类型断言

    TS中实现对象属性必选、对象属性在开发过程中十分常见,前端在传参数时,有些参数比必传,有些是选传,我们可以定一个多个对象来实现传参,但是这让代码变得冗余。我们可以通过TS定义数据类型来实现。 TypeScript中文网 1. 数组 2. 布尔 3. 数值 当我们给num赋值为123但没有

    2024年02月15日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包