Young Kbt blog Young Kbt blog
首页
  • java基础

    • Java基础
    • Java集合
    • Java反射
    • JavaJUC
    • JavaJVM
  • Java容器

    • JavaWeb
  • Java版本新特性

    • Java新特性
  • SQL 数据库

    • MySQL
    • Oracle
  • NoSQL 数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • ActiveMQ
    • RabbitMQ
    • RocketMQ
    • Kafka
  • 进阶服务

    • Nginx
  • Spring
  • Spring Boot
  • Spring Security
  • 设计模式
  • 算法
  • 知识
  • 管理

    • Maven
    • Git
  • 部署

    • Linux
    • Docker
    • Jenkins
    • Kubernetes
  • 进阶

    • TypeScript
  • 框架

    • React
    • Vue2
    • Vue3
  • 轮子工具
  • 项目工程
  • 友情链接
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 关于
    • Vue2-Admin (opens new window)
    • Vue3-Admin(完善) (opens new window)
GitHub (opens new window)

Shp Liu

朝圣的使徒,正在走向编程的至高殿堂!
首页
  • java基础

    • Java基础
    • Java集合
    • Java反射
    • JavaJUC
    • JavaJVM
  • Java容器

    • JavaWeb
  • Java版本新特性

    • Java新特性
  • SQL 数据库

    • MySQL
    • Oracle
  • NoSQL 数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • ActiveMQ
    • RabbitMQ
    • RocketMQ
    • Kafka
  • 进阶服务

    • Nginx
  • Spring
  • Spring Boot
  • Spring Security
  • 设计模式
  • 算法
  • 知识
  • 管理

    • Maven
    • Git
  • 部署

    • Linux
    • Docker
    • Jenkins
    • Kubernetes
  • 进阶

    • TypeScript
  • 框架

    • React
    • Vue2
    • Vue3
  • 轮子工具
  • 项目工程
  • 友情链接
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 关于
    • Vue2-Admin (opens new window)
    • Vue3-Admin(完善) (opens new window)
GitHub (opens new window)
  • 超文本标记语言 - Html

  • 解释编程语言 - JavaScript

  • JS 超集语言 - TypeScript

    • TypeScript - 介绍
    • TypeScript - 安装和使用
    • TypeScript - 基本类型
    • TypeScript - 编译和配置
    • TypeScript - 文件打包
    • TypeScript - 接口
    • TypeScript - 函数
    • TypeScript - 类
    • TypeScript - 泛型
    • TypeScript - 类型推断
    • TypeScript - 高级类型
    • TypeScript Office - 入门
    • TypeScript Office - 常用类型
    • TypeScript Office - 类型缩小
    • TypeScript Office - 更多函数
    • TypeScript Office - 对象类型
    • TypeScript Office - 类型操纵
    • TypeScript Office - 类
    • TypeScript Office - 模块
    • TypeScript Office - 变量声明
    • TypeScript Office - 类型推断
      • 类型推断
      • 最佳公共类型
      • 上下文类型
    • TypeScript Office - 枚举
    • TypeScript Office - 公共类型
    • TypeScript Office - Symbols
    • TypeScript Office - 类型兼容性
    • TypeScript Office - 迭代器和生成器
    • TypeScript Office - 装饰器
    • TypeScript Office - JSX
    • TypeScript Office - 混入
    • TypeScript Office - 三斜线指令
    • TypeScript Office - 模块进阶
    • TypeScript Office - 模块解析
    • TypeScript Office - 命名空间
    • TypeScript Office - 命名空间与模块
    • TypeScript Office - 声明合并
  • 界面构建框架 - React

  • 渐进式框架 - Vue2

  • 渐进式框架 - Vue3

  • 前端
  • JS 超集语言 - TypeScript
Young Kbt
2022-09-13
目录

TypeScript Office - 类型推断

  • 类型推断
  • 最佳公共类型
  • 上下文类型

# 类型推断

在 TypeScript 中,有几个地方在没有显式类型注释的情况下,使用类型推理来提供类型信息。例如,在这段代码中:

// let x: number
let x = 3;
1
2

x 变量的类型被推断为 number。这种推断发生在初始化变量和成员、设置参数默认值和确定函数返回类型时。

在大多数情况下,类型推断是直截了当的。在下面的章节中,我们将探讨类型推断的一些细微差别。

# 最佳公共类型

当从几个表达式中进行类型推断时,这些表达式的类型被用来计算一个「最佳公共类型」。比如说:

// let x: (number | null)[]
let x = [0, 1, null];
1
2

为了推断上面例子中 x 的类型,我们必须考虑每个数组元素的类型。这里我们得到了两个数组类型的选择:number 和 null。最佳公共类型算法考虑了每个候选类型,并选择了与所有其他候选类型兼容的类型。

因为最佳公共类型必须从所提供的候选类型中选择,所以在某些情况下,类型有共同的结构,但没有一个类型是所有候选类型的超级类型。比如说:

// let zoo: (Rhino | Elephant | Snake)[]
let zoo = [new Rhino(), new Elephant(), new Snake()];
1
2

理想情况下,我们可能希望 zoo 被推断为 Animal[],但是因为数组中没有严格意义上的 Animal 类型的对象,所以我们没有对数组元素类型进行推断。为了纠正这一点,当没有一个类型是所有其他候选类型的超级类型时,就明确地提供类型。

// let zoo: Animal[]t
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
1
2

当没有找到最好的共同类型时,产生的推论是联合数组类型,Rhino | Elephant | Snake)[]。

# 上下文类型

在 TypeScript 的某些情况下,类型推理也在「另一个方向」发挥作用。这被称为「上下文类型化」。当表达式的类型被它的位置所暗示时,上下文类型就发生了。比如说:

window.onmousedown = function (mouseEvent) {
    console.log(mouseEvent.button);
    console.log(mouseEvent.kangaroo); // Ⓧ 在'MouseEvent'类型上不存在'kangaroo'属性。
};
1
2
3
4

在这里,TypeScript 类型检查器使用 window.onmousedown 函数的类型来推断赋值右侧的函数表达式的类型。当它这样做时,它能够推断出 mouseEvent 参数的类型,它确实包含一个按钮属性,但不包含袋鼠属性。

这样做的原因是 window 已经在其类型中声明了 onmousedown。

// 声明有一个名为'window'的全局变量
declare var window: Window & typeof globalThis;
// 这被声明为(简化版)。
interface Window extends GlobalEventHandlers {
    // ...
}
// 其中定义了很多已知的处理程序事件
interface GlobalEventHandlers {
    onmousedown: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
    // ...
}
1
2
3
4
5
6
7
8
9
10
11

TypeScript 足够聪明,在其他情况下也能推断出类型:

window.onscroll = function (uiEvent) {
    // Ⓧ 属性 "button" 不存在于 "Event"类型上。
    console.log(uiEvent.button);
};
1
2
3
4

基于上述函数被分配给 Window.onscroll 的事实,TypeScript 知道 uiEvent 是一个 UIEvent,而不是像前面的例子那样是 MouseEvent。UIEvent 对象不包含按钮属性,所以 TypeScript 会抛出一个错误。

如果这个函数不在上下文类型的位置,这个函数的参数将隐含有类型 any,并且不会发出错误(除非你使用 noImplicitAny 选项)。

const handler = function (uiEvent) {
    console.log(uiEvent.button); // <- 正确
};
1
2
3

我们也可以明确地给函数的参数提供类型信息,以覆盖任何上下文的类型。

window.onscroll = function (uiEvent: any) {
    console.log(uiEvent.button); // <- 现在也没有错误
};
1
2
3

然而,这段代码将记录 undefined 的内容,因为 uiEvent 没有名为按钮的属性。

上下文类型化在很多情况下都适用。常见的情况包括函数调用的参数、赋值的右侧、类型断言、对象和数组字面量的成员,以及返回语句。上下文类型也作为最佳普通类型的候选类型。比如说:

function createZoo(): Animal[] {
    return [new Rhino(), new Elephant(), new Snake()];
}
1
2
3

在这个例子中,最佳普通类型有一组四个候选者。Animal,Rhino,Elephant 和 Snake。其中,Animal 可以被最佳共同类型算法所选择。

编辑此页 (opens new window)
#TypeScript
更新时间: 2023/09/18, 16:34:13
TypeScript Office - 变量声明
TypeScript Office - 枚举

← TypeScript Office - 变量声明 TypeScript Office - 枚举→

最近更新
01
技术随笔 - Element Plus 修改包名 原创
11-02
02
Reactor - 扩展性
11-02
03
Reactor - 最佳实践
11-02
更多文章>
Theme by Vdoing | Copyright © 2021-2024 Young Kbt | blog
桂ICP备2021009994号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式