您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

TypeScript 5.3 来了,一大波新特性

时间:2023-11-16 13:19:17  来源:微信公众号  作者:前端充电宝

根据 TypeScript 路线图,TypeScript 5.3 计划于 11 月 14 日发布。

TypeScript 5.3 来了,一大波新特性

下面是该版本带来的新特性:

  • 导入属性
  • 导入类型中稳定支持 resolution-mode
  • 所有模块模式均支持 resolution-mode
  • switch (true) 缩小范围
  • 对布尔值进行比较的缩小范围
  • 通过 Symbol.hasInstance 进行 instanceof 类型缩小
  • 实例字段上的 super 属性访问检查
  • 嵌入提示支持跳转到类型的定义
  • 通过跳过 JSDoc 解析进行优化
  • 通过比较非标准交集进行优化
  • 整合 tsserverlibrary.js 和 typescript.js

导入属性

TypeScript 5.3 支持导入属性提案的最新更新。导入属性的一个用例是向运行时提供有关模块的预期格式的信息。

// 希望将这个文件解释为 JSON 数据,而不是一个带有 .json 扩展名的可执行/恶意的 JAVAScript 文件。
import obj from "./something.json" with { type: "json" };

这些属性的内容不会被 TypeScript 检查,因为它们是特定于宿主环境的,并且会被直接保留,以便浏览器和运行时环境可以处理它们(并可能会出现错误)。

// TypeScript 对此没有问题,但是浏览器可能不支持。
import * as foo from "./foo.js" with { type: "fluffy bunny" };

动态 import() 调用还可以通过第二个参数使用导入属性。

const obj = await import("./something.json", {
    with: { type: "json" }
});

第二个参数的预期类型由名为 ImportCallOptions 的类型定义,该类型默认情况下只需要一个名为 with 的属性。

注意,导入属性是早期提案“导入断言”的演进版本,该提案已在 TypeScript 4.5 中实现。最明显的区别是使用 with 关键字而不是 assert 关键字。但不太明显的区别在于,现在运行时可以自由地使用属性来引导导入路径的解析和解释,而导入断言只能在加载模块后断言某些特征。

随着时间的推移,TypeScript 将逐渐弃用旧的导入断言语法,并倾向于使用导入属性的提案语法。现有使用 assert 的代码应该迁移到使用 with 关键字。需要使用导入属性的新代码应该使用 with。

resolution-mode

导入类型中稳定支持 resolution-mode

在 TypeScript 4.7 中,TypeScript 增加了对 /// <reference types="..." /> 中的 resolution-mode 属性的支持,以控制特定规范符号是应该通过 import 还是 require 语义进行解析。

/// <reference types="pkg" resolution-mode="require" />

// 或

/// <reference types="pkg" resolution-mode="import" />

考虑到导入属性可以引导解析,并且已经看到了合理的使用案例,TypeScript 5.3 现在支持 import type 的 resolution-mode 属性。

// 以使用 `require()` 进行导入的方式解析 `pkg`
import type { TypeFromRequire } from "pkg" with {
  "resolution-mode": "require"
};

// 以使用 `import` 进行导入的方式解析 `pkg`
import type { TypeFromImport } from "pkg" with {
  "resolution-mode": "import"
};

export interface MergedType extends TypeFromRequire, TypeFromImport {}

这些导入属性也可以用于 import() 类型。

export type TypeFromRequire =
  import("pkg", { with: { "resolution-mode": "require" } }).TypeFromRequire;

export type TypeFromImport =
  import("pkg", { with: { "resolution-mode": "import" } }).TypeFromImport;

export interface MergedType extends TypeFromRequire, TypeFromImport {}

所有模块模式均支持 resolution-mode

以前,只有在 moduleResolution 选项为 node16 和 nodenext 时才允许使用 resolution-mode。为了更容易地专门查找用于类型的模块,现在 resolution-mode 在所有其他 moduleResolution 选项中都能正常工作,比如 bundler、node10,在 classic 模式下则不会报错。

类型缩小优化

switch (true)

现在 TypeScript 5.3 能够根据 switch 中每个 case 子句的条件进行类型细化。

function f(x: unknown) {
    switch (true) {
        case typeof x === "string":
            // 这里,'x' 是一个 'string'
            console.log(x.toUpperCase());

        case Array.isArray(x):
            // 这里 'x' 是一个 'string | any[]'
            console.log(x.length);

        default:
          // 这里 'x' 是 'unknown'
          // ...
    }
}

布尔值比较

有时候你可能会在条件语句中直接与 true 或 false 进行比较。通常这些比较是不必要的,但可能出于代码风格或避免 JavaScript 真值方面的某些问题而偏好这种写法。然而,在之前的 TypeScript 版本中,它不能正确地识别这种形式来执行类型缩小。

TypeScript 5.3 现在在缩小变量范围时可以跟上并理解这些表达式。

interface A {
    a: string;
}

interface B {
    b: string;
}

type MyType = A | B;

function isA(x: MyType): x is A {
    return "a" in x;
}

function someFn(x: MyType) {
    if (isA(x) === true) {
        console.log(x.a); // works!
    }
}

Symbol.hasInstance

JavaScript 的一个特性是可以重写 instanceof 运算符的行为。要实现这一点,需要在 instanceof 运算符右侧的值上定义一个名为 Symbol.hasInstance 的特定方法。

class Weirdo {
    static [Symbol.hasInstance](testedValue) {
        return testedValue === undefined;
    }
}

// false
console.log(new Thing() instanceof Weirdo);

// true
console.log(undefined instanceof Weirdo);

为了更好地模拟 instanceof 运算符的行为,TypeScript 现在会检查是否存在 [Symbol.hasInstance] 方法,并且该方法被声明为类型断言函数。如果存在这样的方法,那么通过 instanceof 运算符对左侧测试的值将会被相应地进行类型缩小。

interface PointLike {
    x: number;
    y: number;
}

class Point implements PointLike {
    x: number;
    y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    distanceFromOrigin() {
        return Math.sqrt(this.x ** 2 + this.y ** 2);
    }

    static [Symbol.hasInstance](val: unknown): val is PointLike {
        return !!val && typeof val === "object" &&
            "x" in val && "y" in val &&
            typeof val.x === "number" &&
            typeof val.y === "number";
    }
}


function f(value: unknown) {
    if (value instanceof Point) {
        // 可以访问这两个属性 - 正确!
        value.x;
        value.y;

        // 无法访问这个属性,有 'PointLike' 类型的对象,但实际上并没有 'Point' 类型的对象。
        value.distanceFromOrigin();
    }
}

在这个例子中,Point 定义了自己的 [Symbol.hasInstance]方法。它实际上充当了一个对称为 PointLike 的独立类型的自定义类型保护程序。在函数 f 中,我们能够通过 instanceof 将 value 缩小到 PointLike 类型,但无法缩小到 Point 类型。这意味着可以访问属性 x 和 y,但无法访问 distanceFromOrigin 方法。

实例字段上的 super 属性访问检查

在 JavaScript 中,可以通过 super 关键字访问基类中的声明。

class Base {
    someMethod() {
        console.log("Base method called!");
    }
}

class Derived extends Base {
    someMethod() {
        console.log("Derived method called!");
        super.someMethod();
    }
}

new Derived().someMethod();

// 输出结果:
//   Derived method called!
//   Base method called!

这与编写像 this.someMethod() 这样的代码是不同的,因为那样可能会调用一个被重写的方法,如果一个声明根本没有被重写,那么通常这两种方式是可以互换的。

class Base {
    someMethod() {
        console.log("someMethod called!");
    }
}

class Derived extends Base {
    someOtherMethod() {
        // These act identically.
        this.someMethod();
        super.someMethod();
    }
}

new Derived().someOtherMethod();

// 输出结果:
//   someMethod called!
//   someMethod called!

问题在于这两种方式是不能互换使用的,因为 super 只能用于在原型上声明的成员,而不能用于实例属性。这意味着如果你写了 super.someMethod(),但 someMethod 被定义为一个字段,那么就会出现运行时错误!

class Base {
    someMethod = () => {
        console.log("someMethod called!");
    }
}

class Derived extends Base {
    someOtherMethod() {
        super.someMethod();
    }
}

new Derived().someOtherMethod();

TypeScript 5.3 现在更仔细地检查 super 属性访问/方法调用,以查看它们是否对应于类字段。如果是的话,现在会得到一个类型检查错误。

嵌入提示支持跳转到类型的定义

TypeScript 的嵌入提示现在支持跳转到类型的定义!

TypeScript 5.3 来了,一大波新特性

按住 Ctrl 键单击嵌入提示可跳转至参数类型的定义。

通过跳过 JSDoc 解析进行优化

通过 tsc 运行 TypeScript 时,编译器现在将避免解析 JSDoc。这不仅减少了解析时间,还减少了存储注释的内存使用量以及垃圾收集所花费的时间。可以在 --watch 模式下看到稍快的编译速度和更快的反馈。

通过比较非标准交集进行优化

在 TypeScript 中,并集和交集始终遵循特定的形式,其中交集不能包含并集类型。这意味着当我们在 A & (B | C) 这样的并集上创建交集时,该交集将被标准化为 (A & B) | (A & C)。尽管如此,在某些情况下,类型系统仍会出于显示目的而保留原始形式。

举个例子,假设我们有 SomeType & (Type1 | Type2 | ... | Type99999NINE),我们想要确定它是否可以赋值给 SomeType,源类型是一个看起来像 (SomeType & Type1) | (SomeType & Type2) | ... |(SomeType & Type99999NINE) 的联合类型。在检查一个联合类型是否可以赋值给某个目标类型时,必须检查联合类型的每个成员是否可以赋值给目标类型,这可能会非常慢。

在 TypeScript 5.3 中,当比较类型时,会快速检查目标类型是否存在于源交集中的任何成员中。

整合 tsserverlibrary.js 和 typescript.js

TypeScript 本身提供了两个库文件:tsserverlibrary.js 和 typescript.js。在 tsserverlibrary.js 中只有特定的 API(例如 ProjectService API)。然而,这两个是不同包,它们有许多重叠之处,在包中重复了很多代码。更重要的是,由于自动导入或肌肉记忆,要始终一致地使用其中一个可能会很具有挑战性。意外加载两个模块太容易了,代码在不同的 API 实例上可能无法正常工作。即使它能够正常工作,加载第二个包会增加资源使用率。

鉴于此,TypeScript 团队决定整合两者。 typescript.js 现在包含 tsserverlibrary.js 的内容,并且 tsserverlibrary.js 现在只是重新导出 typescript.js。整合之后,包大小减少了 20.5%。



Tags:TypeScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
一篇文章搞懂TypeScript
TypeScript 是 JavaScript 的超集,一方面给动态类型的 js 增加了类型校验,另一方面扩展了 js 的各种功能。原始数据类型 字符串 数值 布尔 null undefined Symbol BigIntlet s...【详细内容】
2024-01-08  Search: TypeScript  点击:(76)  评论:(0)  加入收藏
TypeScript中的null和undefined的区别
在TypeScript中,null和undefined是两个特殊的值,用于表示变量的缺失或未定义。尽管它们在某些情况下可能看起来相似,并且都可以表示"没有值",但它们在语义和用法上存在一些重要...【详细内容】
2023-12-07  Search: TypeScript  点击:(132)  评论:(0)  加入收藏
为什么要在项目中使用TypeScript?
译者 | 李睿随着越来越多的开发人员采用TypeScript,人们需要了解在下一个项目中应该使用TypeScript的原因。尽管它在早期应用中遇到了一些阻力,但在过去十年,它迅速成为一种广...【详细内容】
2023-11-30  Search: TypeScript  点击:(162)  评论:(0)  加入收藏
一文读懂 TypeScript 泛型及应用
泛型是静态类型语言的基本特征,允许将类型作为参数传递给另一个类型、函数、或者其他结构。TypeScript 支持泛型作为将类型安全引入组件的一种方式。这些组件接受参数和返回...【详细内容】
2023-11-20  Search: TypeScript  点击:(193)  评论:(0)  加入收藏
TypeScript 5.3 来了,一大波新特性
根据 TypeScript 路线图,TypeScript 5.3 计划于 11 月 14 日发布。下面是该版本带来的新特性: 导入属性 导入类型中稳定支持 resolution-mode 所有模块模式均支持 resolution-...【详细内容】
2023-11-16  Search: TypeScript  点击:(153)  评论:(0)  加入收藏
万字详解 TypeScript 高级用法
TypeScript 是一种类型安全的 JavaScript 超集,除了基本类型和对象类型之外,TypeScript 还提供了一些高级类型系统,使得我们可以更好地处理复杂的数据结构和业务逻辑。本文将深...【详细内容】
2023-10-31  Search: TypeScript  点击:(339)  评论:(0)  加入收藏
不要在Typescript中使用Function类型
原文链接:https://www.totaltypescript.com/dont-use-function-keyword-in-typescript翻译:一川在Typescript中不应该使用Function作为一个类型,因为它可以表示任何函数。通常,...【详细内容】
2023-09-27  Search: TypeScript  点击:(279)  评论:(0)  加入收藏
为什么选择 TypeScript,它有什么优点吗?
在当今快速发展的软件开发领域,TypeScript技术的重要性日益凸显。TypeScript是一种由微软开发的开源编程语言,它扩展了JavaScript,并为开发者提供了强大的静态类型检查。首先,Ty...【详细内容】
2023-09-22  Search: TypeScript  点击:(191)  评论:(0)  加入收藏
掌握TypeScript,开启高质量前端之旅
相信TypeScript对于一个前端开发来讲应该是不陌生的,因为作为一个前端开发者来说,不是在学习如何使用TS就是在去学习TS如何使用的路上。为什么这么说呢?一些技术的发展离不开人...【详细内容】
2023-09-22  Search: TypeScript  点击:(283)  评论:(0)  加入收藏
反驳来了!放弃TypeScript?说明你无知!
作者 | Robert Vitonsky编译 | 云中 几天前,汉森 (David Heinemeier Hansson)宣布 Turbo8 即将放弃 TypeScript。我心想:放弃就放弃吧,反正我也不知道 Turbo 8 是什么鬼。 然而...【详细内容】
2023-09-15  Search: TypeScript  点击:(232)  评论:(0)  加入收藏
▌简易百科推荐
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(5)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(12)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(8)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(10)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(8)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  云原生散修  微信公众号  Tags:Kubernetes   点击:(5)  评论:(0)  加入收藏
站内最新
站内热门
站内头条