我试图理解为什么 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 不知道
filter
的作用,因此它不知道何时调用其回调(现在同步,或稍后异步),因此不知道对象是否被范围之外的其他代码更改。功能。函数外部代码的更改可能会使类型保护无效。
但是通过有趣命名的
variable
常量,TypeScript 知道该值不能更改,因此可以应用类型保护。如果您使用 let
而不是 const
,它甚至可以工作,因为 TypeScript 可以看到没有任何对 variable
的赋值。 (但是,如果您使用 let
并且在 variable = undefined;
调用之后添加了
filter
,您将得到与
param.optional
相同的错误,因为 TypeScript 再次不知道回调的代码何时相对于该作业:示例。)