阅读 386

【译】Typescript 4.0 beta 常用新特性一览

Typescript 4.0 beta

  • 2020年的7月26号,微软发布了 TypeScript 4.0 beta。
  • 这里主要是对几个主要的特性做一下自己浅显的理解。

相关文章导航

0、怎么使用

npm install typescript@beta
// or
yarn add typescript@beta
复制代码

几个重要的新特性

1、/* @deprecated / 支持

  • 不建议/不赞成使用 注释
    • 在我们实际使用的场景中其实用户很大,在新老工程替换的时候,为了维护老项目和代码的继续正常运行。
    • 有些年老的代码(bad smell)不得不留在代码中,但是又不希望萌新同事使用这些方法,就可以上这个注释,用来更好警告使用者不要使用这里的代码。

image

2、Insiders 编辑器支持部分编辑/加载模式

  • Typescript 编译的时候很慢,特别是大项目,应该不少小伙伴都会遇到这个问题。

具体来说,罪魁祸首通常是一个称为项目加载的过程,该过程与我们的编译器的程序构建步骤大致相同。这是从一组初始文件开始,解析它们,解析它们的依存关系,解析那些依赖关系,解析那些依赖关系的依赖关系(开始各种套娃)等等的过程。

当前,唯一支持此模式的编辑器是Visual Studio Code Insiders,您可以按照以下步骤尝试。

简单来说 ts4.0 beta 就是在允许配置单个文件视图 ts 编译模式,让以前的启动项目的时候 20s + 的时间缩短到 2-5s 左右。

3、更智能的自动导入

  • 自动导入是一直有的,在我们在package.json 引入一个 dependencies 因为使用 ts 的缘故,我们一般会加上 @types 相关的包。以前由于 ts 的特性,自动导入的时候会做很多额外的操作,比如会进行所有 node_modules 的 type checking (类型检测)。
  • 在 4.0 中我们的 ts 在自动导入需要的 @types 而不做额外的操作。
打开JSON设置视图: > Preferences: Open Settings (JSON)
添加以下行:

// The editor will say 'dynamic' is an unknown option,
// but don't worry about it for now. It's still experimental.
"typescript.tsserver.useSeparateSyntaxServer": "dynamic",
复制代码

4、unknowncatch 中允许使用

  • 以前我们在 try catch 使用
try {
    // ...
}
catch (x) {
    // x has type 'any' - have fun!
    console.log(x.message);
    console.log(x.toUpperCase());
    x++;
    x.yadda.yadda.yadda();
}
复制代码
  • 现在就加上了 unknown
try {
    // ...
}
catch (e: unknown) {
    // error!
    // Property 'toUpperCase' does not exist on type 'unknown'.
    console.log(e.toUpperCase());

    if (typeof e === "string") {
        // works!
        // We've narrowed 'e' down to the type 'string'.
        console.log(e.toUpperCase());
    }
}
复制代码

5、可变参数的元祖类型(Variadic Tuple Types)

function concat(arr1, arr2) {
    return [...arr1, ...arr2];
}

// 返回除第一个元素外的其他所有元素
function tail(arg) {
    const [_, ...result] = arg;
    return result
}
复制代码

4.1 思考怎么在 ts 中键入

  • 简单的方法就是使用 函数重载 来实现,来看一个例子
// 其中 A,B,C,D 是不同基本类型
function concat<>(arr1: [], arr2: []): [A];
function concat<A>(arr1: [A], arr2: []): [A];
function concat<A, B>(arr1: [A, B], arr2: []): [A, B];
function concat<A, B, C>(arr1: [A, B, C], arr2: []): [A, B, C];
function concat<A, B, C, D>(arr1: [A, B, C, D], arr2: []): [A, B, C, D];
function concat<A, B, C, D, E>(arr1: [A, B, C, D, E], arr2: []): [A, B, C, D, E];
function concat<A, B, C, D, E, F>(arr1: [A, B, C, D, E, F], arr2: []): [A, B, C, D, E, F];)
复制代码

4.2 上面还只是为了给 arr1 支持不同类型,函数重载已经比较复杂了。

  • 当我们要支持 arr2 的不同类型的时候会更加的复杂
function concat<A2>(arr1: [], arr2: [A2]): [A2];
function concat<A1, A2>(arr1: [A1], arr2: [A2]): [A1, A2];
function concat<A1, B1, A2>(arr1: [A1, B1], arr2: [A2]): [A1, B1, A2];
function concat<A1, B1, C1, A2>(arr1: [A1, B1, C1], arr2: [A2]): [A1, B1, C1, A2];
function concat<A1, B1, C1, D1, A2>(arr1: [A1, B1, C1, D1], arr2: [A2]): [A1, B1, C1, D1, A2];
function concat<A1, B1, C1, D1, E1, A2>(arr1: [A1, B1, C1, D1, E1], arr2: [A2]): [A1, B1, C1, D1, E1, A2];
function concat<A1, B1, C1, D1, E1, F1, A2>(arr1: [A1, B1, C1, D1, E1, F1], arr2: [A2]): [A1, B1, C1, D1, E1, F1, A2];
复制代码

4.3 从这里可以看到,如果我们要在 ts 中实现 tail 函数的话,我们的重载函数的复杂度就会无穷尽的增长。官方叫他 This is another case of what we like to call “death by a thousand overloads”

  • 谈到 overload 这里肯定会想到 -地表最强骨法师 飞鼠- 被 1000 个骨王 x 倒(大雾)。

image

不好意思放错图了,看这个👇

image

4.4 ts 4.0 做的事情就是,允许了元组的扩展符号的签名使用

function concat<T, U>(arr1: T[], arr2, U[]): Array<U>;

function tail<T extends any[]>(arr: readonly [any, ...T]) {
    const [_ignored, ...rest] = arr;
    return rest;
}

const myTuple = [1, 2, 3, 4] as const;
const myArray = ["hello", "world"];

// type [2, 3, 4]
const r1 = tail(myTuple);

// type [2, 3, ...string[]]
const r2 = tail([...myTuple, ...myArray] as const);
复制代码

4.5 第二个改变就是允许了在元组中扩展符的任意使用,不仅仅是在最后。也再也不会看到这个报错提示了

error: A rest element must be last in a tuple type.
复制代码
  • demo
type Strings = [string, string];
type Numbers = [number, number];

// [string, string, number, number]
type StrStrNumNum = [...Strings, ...Numbers];
Previously, TypeScript would issue an error like the following.
复制代码

4.6 最后我们来根据 ts 提供的新特性实现 concat 函数的定义

type Arr = readonly any[];

function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
    return [...arr1, ...arr2];
}
复制代码

6、更多...

参考