英文:
Type guard not being identified when assigned to boolean - strict mode
问题
以下是翻译好的内容:
我有以下的代码:
两个类型保护中的条件相同,但只有第二个起作用。我很想理解为什么?
```typescript
export class MessageService {
private _iframe?: HTMLIFrameElement;
sendMessage() {
const appLoaded = !!this._iframe?.contentWindow;
// 为什么这个不起作用?
if (appLoaded) {
this._iframe.contentWindow.postMessage({}, '*'); // 错误
}
// 而这个却可以
if(!!this._iframe?.contentWindow) {
this._iframe.contentWindow.postMessage({}, '*');
}
}
}
谢谢!
注意:我已经删除了代码部分,只提供了翻译好的文本。
<details>
<summary>英文:</summary>
I have the following code:
The condition is the same in both typeguards, but only the second one works. I'd love to understand why?
export class MessageService {
private _iframe?: HTMLIFrameElement;
sendMessage() {
const appLoaded = !!this._iframe?.contentWindow;
// why does this not work?
if (appLoaded) {
this._iframe.contentWindow.postMessage({}, '*'); // ERROR
}
// while this does
if(!!this._iframe?.contentWindow) {
this._iframe.contentWindow.postMessage({}, '*');
}
}
}
[TS Playground link][1]
Thanks!
[1]: https://www.typescriptlang.org/play?#code/KYDwDg9gTgLgBAYwDYEMDOa4FlgZQc2AGVgoA3ASwWDgG8AoOOMKCslGGgfQoDMoUAW2AB%20AFxwAEgBUsAGQCSAMQHCAokmDCAdjADc9RnDTBtAExx5CACgCUdI0wQRtaeCjBg5EFGeBm4AF44AEIQmAALCjQAOh5%20IVEY511TGAB1CnMIAHcDRzgAekK4HIiATzgzCFw4SOi4bQh4HOgAaxECvjhrDy8fPzN7BiZR0frY%20NVgZJdOXUzsnJjIN0s0AmBrWgBfABo4AHIAKkPbAzGdwzHi0qjNOqjMatwu3mswibi%20aZFZ1IWWWqOWGBTGXymiX%208wyQNyKwga1wGxsuwOJzOF1GVyYVx2QA
</details>
# 答案1
**得分**: 0
因为TypeScript的流分析不会走得那么远。它不会跟踪`appLoaded`为`true`也意味着`this._iframe?.contentWindow`也为真的事实。这只是编译器的实际限制。从理论上讲,它是可以做到的(直到/除非在分配之后并在使用`contentWindow`之前调用函数,此时`this._iframe`和/或`this._iframe.contentWindow`可能已经改变),但这样做足够复杂,以至于不值得。
如果你想避免重复条件,你可以始终像这样做:
```javascript
const wnd = this._iframe?.contentWindow;
// ...
if (wnd) {
wnd.postMessage({}, '*');
}
英文:
Because TypeScript's flow analysis doesn't go that far. It doesn't track the fact that appLoaded
being true
also means that this._iframe?.contentWindow
is also truthy. It's just a pragmatic limitation of the compiler. In theory, it could do it (until/unless you called a function after the assignment and before using contentWindow
, at which point this._iframe
and or this._iframe.contentWindow
may have changed), but doing that is complex enough that it doesn't.
You could always do something like this, if you want to avoid repeating the condition:
const wnd = this._iframe?.contentWindow;
// ...
if (wnd) {
wnd.postMessage({}, '*');
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论