TypeScript 5.4:带来新的类型和一些 Break Change

2024-02-22 08:37:39 浏览数 (2)

大家好,我是 ConardLi

大家好,最近 TypeScript 发布了 5.4 Beta 版本,其中包含了一些值得关注的新特性以及一些 Break Change,我们一起来看下吧:

优化闭包中的类型收窄

“类型收窄” 在 TypeScript 中是一个常见的类型推断过程,基于我们可能进行的某些检查或条件,TypeScript 能够自动推断出变量的具体类型,这就使得该变量的类型范围被“缩小”或者说“窄化”。这项特性可以帮助我们编写更加准确、安全的代码。

代码语言:javascript复制
function uppercaseStrings(x: string | number) {
    if (typeof x === "string") {
        // TypeScript在这里知道'x'是一个'string'
        return x.toUpperCase();
    }
}

一个常见的痛点是,我们在闭包函数里是感知不到这些被收窄后的类型的。

代码语言:javascript复制
function getUrls(url: string | URL, names: string[]) {
    if (typeof url === "string") {
        url = new URL(url);
    }

    return names.map(name => {
        url.searchParams.set("name", name)
        //  ~~~~~~~~~~~~
        // error!
        // Property 'searchParams' does not exist on type 'string | URL'.

        return url.toString();
    });
}

在代码中,我们首先检查了 url 的类型,如果 url 是字符串(即 typeof url === "string"),我们把它转化为 URL 对象。在这个语句块中,TypeScript 能够理解 url 已经不再是一个字符串,而是一个 URL 对象,因此我们可以在后面调用 URL 对象的 searchParams 属性。

可是,在数组的 map 方法中,TypeScript 不能保证 url 的类型已经窄化为 URL,因为他无法确定在回调函数被执行的当下,url是否仍然是 URL 对象,这是因为在函数的闭包中,变量可能会被之后的代码改变,因此 TS 认为这种类型窄化是不安全的。

但其实在这个例子中,这个箭头函数肯定是在对 url 进行类型变更后被创建的,并且对 url 的类型变更是最后的赋值操作,所以 url 在这个函数中的类型就是我们赋值的类型。

因此,TypeScript 5.4 做了改进,当参数和 let 变量在非提升函数中使用时,类型检查器将查找最后一个赋值点。如果找到一个,TypeScript 可以从包含该函数的外部安全地窄化,那上面的代码示例就可以正常工作了。

但是还需要注意一点,如果我们是在嵌套函数中的任何地方对变量进行了赋值,类型收窄还是不起作用的。这是因为我们没有办法确保是否会在以后调用该函数。

代码语言:javascript复制
function printValueLater(value: string | undefined) {
    if (value === undefined) {
        value = "missing!";
    }

    setTimeout(() => {
        // Modifying 'value', even in a way that shouldn't affect
        // its type, will invalidate type refinements in closures.
        value = value;
    }, 500);

    setTimeout(() => {
        console.log(value.toUpperCase());
        //          ~~~~~
        // error! 'value' is possibly 'undefined'.
    }, 1000);
}

Github 上有个 Issue 就是讨论这个问题的,感兴趣可以看看:https://github.com/microsoft/TypeScript/pull/56908

我之前的文章:什么是鸭子

0 人点赞