打字稿缩小不适用于嵌套函数的真实性

问题描述

在共享代码 (Playground Link) 中,编译器抛出错误 Object is possibly 'null'.

是否有可能调用 refresh 以便 viewer 可以为 null,前提是在 viewer 函数topLayer 为 null 时提前返回?

如果不是,在嵌套函数的情况下,打字稿没有缩小范围的原因是什么?

解决方法

这里有点接近,但显然不是同一个精心设计的例子:

declare var viewer: { key: string } | null;

let _viewer = { key: 'key' } as { key: string } | null

Object.defineProperty(window,'viewer',{
  get() {
    const val = _viewer;
    _viewer = null;
    return val
  }
})

function topLayer() {
  if (!viewer) return;
  function refresh() {
    console.log(viewer.key); // shows `Cannot read property 'key' of null` error
  }
  refresh();
}

topLayer();

playground link

尽管实际上 typescript 使用了一些启发式来缩小类型,但显然不会使用 viewer 变量的所有可能值运行您的程序。新函数 refreshviewer 自由(不是局部变量也不是参数)变量创建新的作用域,但它仍未缩小范围。

如果你改写为:

function topLayer() {
  if (!viewer) return;
  function refresh(viewer: { key: string }) {
    console.log(viewer.key);
  }
  refresh(viewer);
}

playground link

一切都按预期进行。