typescript - 如何将类型谓词分配给变量
问题描述
我有一个代码:
let point: number | undefined;
let point2: number;
const isPointNotUndefined = point !== undefined;
if (isPointNotUndefined) {
point2 = point;
}
TypeScript 说“Type 'number | undefined'
不可分配给类型number
”但如果我接下来这样做:
if (point !== undefined) {
point2 = point;
}
这很好用。
如何解释打字稿在变量中执行类型谓词,而不创建函数?
解决方案
TS4.4 更新:
TypeScript 4.4 将引入对将某些类型保护的结果保存到 a 的支持const
,如microsoft/TypeScript#44730中所实现的那样。不幸的是,您在此处的特定示例将继续不起作用,因为point
它是一个可变变量,并且编译器不会花费必要的资源来确保在分配和检查它point
之间实际上没有重新分配。isPointNotUndefined
如果您创建point
一个const
或一个函数参数,那么编译器将假定它point
没有被重新分配并将isPointNotUndefined
用作类型保护:
function foo(point: number | undefined) {
let point2: number;
const isPointNotUndefined = point !== undefined;
if (isPointNotUndefined) {
point2 = point; // okay
}
}
TS4.3 及以下版本的答案:
目前在 TypeScript 中无法将类型保护的结果存储在布尔变量中。GitHub 中有两个开放的功能请求:microsoft/TypeScript#12184和microsoft/TypeScript#24865。根据TypeScript 首席架构师的评论,
这将要求我们跟踪一个变量的特定值对其他变量的影响,这将增加控制流分析器的大量复杂性(以及相关的性能损失)。不过,我们会将其保留为建议。
因此,它不太可能很快实现,除非有人可以提出一种不会显着降低编译器性能的方法。如果你有这样的提议,你可能想去#24865 并提出它。否则,您总是可以给他们每个人添加另一个投票,但务实地说,您应该继续进行,就好像这永远不会发生一样。
解决方法是您已经知道但不想使用的方法。为了完整起见,您可以执行内联检查:
if (point !== undefined) {
point2 = point;
}
或者如果检查写起来很麻烦,请为其创建一个用户定义的类型保护函数:
const isDefined = <T,>(x: T | undefined): x is T => typeof x !== "undefined";
if (isDefined(point)) {
point2 = point;
}
由于检查undefined
是如此之快,我怀疑任何其他解决方法都不会那么麻烦。不过,另一种方法是将任何“检查有效性和值”操作表示为有区别的 union,例如:
type DefinedUnion<T> =
{ defined: true, value: Exclude<T, undefined> } |
{ defined: false, value: undefined };
可区分联合具有将“检查”存储为可区分属性的优点。当然,将值转换为 a 的形式DefinedUnion
需要更多代码:
function toDefinedUnion<T>(x: T | undefined): DefinedUnion<T> {
return { defined: typeof x !== "undefined", value: x } as DefinedUnion<T>
}
const pointU = toDefinedUnion(point);
但是它很容易使用。
if (pointU.defined) {
point2 = pointU.value; // okay
}
同样,这不是我建议替换单个“is this undefined
”检查的方法。但是,如果您的“这是一件有效的事情”检查足够昂贵,以至于您真的只想做一次,那么有区别的工会可能是要走的路。
推荐阅读
- operating-system - 如何在分段内存管理中生成逻辑地址
- reactjs - 使用 Formik 降档自动完成 onBlur 重置值
- javascript - TypeError:无法读取 null 的属性“createElement”
- autohotkey - AutoHotKey 可以拦截鼠标点击吗?
- javascript - 如何在另一个数组中找到数组的每个值?
- aws-lambda - 在 Lambda 函数中获取 API Gateway 的 IP 地址(通过 Python)
- perl - 迭代数组引用并在 perl 中转换为哈希
- java - 汤 | 获取部分 HTML
- python - 消除稀疏矩阵数据集中的零
- python - 为最多具有 1 或 True 的“m”个元素的“n”个布尔元素生成所有可能的排列