为什么缩小闭包内部的范围不适用于属性对象,但适用于声明的变量?

问题描述 投票:0回答:1

我试图理解为什么 Typescript 无法正确获取内部函数内的对象属性参数的类型,该参数可能是未定义的,但是当在外部函数作用域中将相同的属性分配给其自己的变量时,缩小会无缝发生。

我有这个片段来重现问题:

type MyType = {
    optional?: string
}

(arr: string[], param: MyType) => {

    if (param.optional) {
        const includes = arr.includes(param.optional)  // <-- Fine

        arr.filter(function (item) {
            return item.includes(param.optional)  // <-- Wrong! Type undefined is not assignable...
        })
    }
}

在 if 分支内,Typescript 会警告我在过滤器内部函数中使用

param.optional
,因为它可能是
string | undefined
,无论在
arr.includes(param.optional)
内部使用它时根本没有警告。

这对我来说似乎很奇怪,因为如果我不使用

param.optional
,而是将相同的值分配给自己的变量,Typescript 就能够完美地缩小其类型(
string
)。

type MyType = {
    optional?: string
}

(arr: string[], param: MyType) => {
    const variable = param.optional

    if (variable) {
        const includes = arr.includes(variable)  // <-- Fine

        arr.filter(function (item) {
            return item.includes(variable)  // <-- Fine
        })
    }
}

为什么会出现这种行为?它与对象本身有什么关系(因为如果参数只是一个原始可选值

string | undefined
就不会出现这个问题)?

typescript types closures
1个回答
0
投票

因为一般情况下这样做是不安全的。

TypeScript 不知道

filter
的作用,因此它不知道何时调用其回调(现在同步,或稍后异步),因此不知道对象是否被范围之外的其他代码更改。功能。函数外部代码的更改可能会使类型保护无效。

但是通过有趣命名的

variable
常量,TypeScript 知道该值不能更改,因此可以应用类型保护。如果您使用
let
而不是
const
,它甚至可以工作,因为 TypeScript 可以看到没有任何对
variable
的赋值。 (但是,如果您使用
let
并且在 variable = undefined;
 调用之后添加了 
filter
,您将得到与 
param.optional
 相同的错误,因为 TypeScript 再次不知道回调的代码何时相对于该作业:
示例。)

© www.soinside.com 2019 - 2024. All rights reserved.