TypeScript Narrowing 的概念

简介: TypeScript Narrowing 的概念

如何实现下列这个函数?


function padLeft(padding: number | string, input: string) {
}

image.png


编译错误的原因:


TypeScript 警告我们将数字添加到数字 | string 可能不会给我们想要的东西,这是对的。 换句话说,我们没有先明确检查 padding 是否是数字,也没有处理它是字符串的情况。


正确的做法:


function padLeft(padding: number | string, input: string) {
  if (typeof padding === "number") {
    return new Array(padding + 1).join(" ") + input;
  }
  return padding + input;
}

如果这看起来像是无趣的 JavaScript 代码,那就是重点。除了我们放置的注释之外,这个 TypeScript 代码看起来像 JavaScript。这个想法是 TypeScript 的类型系统旨在使编写典型的 JavaScript 代码尽可能容易。


虽然它看起来可能不多,但实际上这里有很多事情要做。就像 TypeScript 如何使用静态类型分析运行时值一样,它将类型分析覆盖在 JavaScript 的运行时控制流结构上,例如 if/else、条件三元组、循环、真实性检查等,这些都会影响这些类型。


在我们的 if 检查中,TypeScript 看到 typeof padding === “number” 并将其理解为一种称为类型保护(Type guard)的特殊代码形式。 TypeScript 遵循可能的执行路径,我们的程序可以采用这些路径来分析给定位置的值的最具体可能类型。它着眼于这些特殊检查(称为类型保护)和赋值,并将类型细化为比声明的类型更具体的类型的过程称为缩小。在许多编辑器中,我们可以观察这些类型的变化。


比如,在第二个 return 语句里,因为前一个 IF 语句的条件没有满足,所以代码执行到这里时,padding 的类型一定只能是 string 了。


image.png


看下面这段代码:


function printAll(strs: string | string[] | null) {
  if (typeof strs === "object") {
    for (const s of strs) {
      console.log(s);
    }
  } else if (typeof strs === "string") {
    console.log(strs);
  } else {
    // do nothing
  }
}

编译错误:Object is possibly ‘null’.

image.png


在 printAll 函数中,我们尝试检查 strs 是否为对象以查看它是否为数组类型(现在可能是强调数组是 JavaScript 中的对象类型的好时机)。 但事实证明,在 JavaScript 中,typeof null 实际上是“object”! 这是历史上的不幸事故之一。


有足够经验的用户可能不会感到惊讶,但并不是每个人都在 JavaScript 中遇到过这种情况; 幸运的是,TypeScript 让我们知道 strs 只缩小到 string[] | null 而不仅仅是 string[]。


这可能是我们所谓的“真实性”检查的一个很好的过渡。


双感叹号是 Boolean 函数调用的简写形式。


因此上面的代码可以修改成:





使用 in 关键字进行的 narrowing

function printAll(strs: string | string[] | null) {
  if (strs && typeof strs === "object") {
    for (const s of strs) {
      console.log(s);
    }
  } else if (typeof strs === "string") {
    console.log(strs);
  } else {
    // do nothing
  }
}

Javascript 有一个运算符来确定对象是否具有带名称的属性:in 运算符。 TypeScript 将这一点作为缩小潜在类型的一种方式。


例如,使用代码:x 中的“值”。 其中“value”是字符串文字,x 是联合类型。 “true”分支缩小了具有可选或必需属性值的 x 类型,“false”分支缩小到具有可选或缺失属性值的类型。


例子:


type Fish = { swim: () => void };

type Bird = { fly: () => void };


function move(animal: Fish | Bird) {

 if ("swim" in animal) {

   return animal.swim();

 }


 return animal.fly();

}

1

2

3

4

5

6

7

8

9

10

/118191351

相关文章
|
6小时前
|
JavaScript 前端开发 数据安全/隐私保护
TypeScript中装饰器的概念与使用场景
【4月更文挑战第23天】TypeScript的装饰器是特殊声明,用于附加到类的声明、方法、属性或参数,以修改行为。它们以`@expression`形式,其中`expression`是运行时调用的函数。装饰器应用场景包括:日志记录、调试、依赖注入、权限控制和AOP。通过装饰器,可以实现动态行为修改,如添加日志、注入依赖、控制权限以及事务管理。然而,应谨慎使用,避免过度复杂化代码。装饰器在现代 TypeScript 开发中扮演重要角色,帮助编写更健壮、可维护的代码。
|
7月前
|
资源调度 JavaScript 前端开发
【TypeScript】Ts基本概念
【TypeScript】Ts基本概念
46 0
|
7小时前
|
存储 JavaScript 算法
TypeScript算法专题 - [双链表1] - 双链的概念及其实现
TypeScript算法专题 - [双链表1] - 双链的概念及其实现
28 0
|
7小时前
|
JavaScript 前端开发 程序员
TypeScript【枚举、联合类型函数_基础、函数_参数说明 、类的概念、类的创建】(二)-全面详解(学习总结---从入门到深化)
TypeScript【枚举、联合类型函数_基础、函数_参数说明 、类的概念、类的创建】(二)-全面详解(学习总结---从入门到深化)
20 0
|
9月前
|
存储 JavaScript 安全
TypeScript中的泛型:深入理解泛型的概念和应用场景
TypeScript中的泛型:深入理解泛型的概念和应用场景
|
10月前
|
JavaScript 前端开发
【TypeScript】原始数据的类型详解概念
【TypeScript】原始数据的类型详解概念
|
10月前
|
JavaScript 前端开发 程序员
TypeScript 系列(一):TS 核心概念
TypeScript 系列(一):TS 核心概念
90 0
|
JavaScript 前端开发 Scala
TypeScript Mixins 概念介绍
TypeScript Mixins 概念介绍
159 0
TypeScript Mixins 概念介绍
|
JavaScript 前端开发 编译器
TypeScript 里的 module 概念
TypeScript 里的 module 概念
179 0
|
JavaScript 前端开发
TypeScript Narrowing 的概念
TypeScript Narrowing 的概念
115 0
TypeScript Narrowing 的概念