如果我使用(严格的空判断)类型脚本,并且我有一些代码可能带有空变量:

let x = null;
if (someCondition) {
  x = { a: 1 };
}

doSomethingWith(x.a);

不出所料,我收到了一个错误:

"x"可能为"Null".

我可以用一张null英镑的支票来修正这个错误:

if (!x) return;
doSomethingWith(x.a);

但后来我得到了:

类型‘Never’上不存在属性‘a’.

实际上,我想写的不是if/return,而是assert呼叫:

const assert = value => { if (!value) throw Error(); }

assert(x);
doSomethingWith(x.a);

...但这并不能消除第一个错误.

我想我可以用以下方法修复第二个错误:

(rootGroup as {id: number}).id

但我不确定这是否是最简单的解决方案,而且它仍然不能解决使用assert函数的问题.

我的问题是,我怎么才能...?

  1. 创建一个"可能为空"的变量
  2. 运行一个证明它不为空的函数(如果为空则抛出错误)
  3. 添加(尽可能少的)打字代码,然后
  4. 使用该变量,没有任何TS错误

推荐答案

您可以像这样使用assertion signatures:

let x: { a: 1 } | null = null

if (someCondition) {
  x = { a: 1 }
}

// @ts-expect-error x maybe null
console.log(x.a)

assert(x) // asserting that x is truthy

console.log(x.a) // no error here

function assert(value: unknown): asserts value {
  if (!value) {
    throw new Error('foo')
  }
}

如果您只想抛出空值,您可以这样做:

function assertNotNull<T>(value: T): asserts value is NonNullable<T> {
  if (value == null) {
    throw new Error('bar')
  }
}

Playground

Typescript相关问答推荐

在Angular中,如何在文件上传后清除文件上传文本框

角形标题大小写所有单词除外

在MessageStore对象中实现条件类型时出现TypeScrip错误

是否有一个版本的联合类型递归地使属性只出现在一个可选选项中?

为什么有条件渲染会导致material 自动完成中出现奇怪的动画?

<;T扩展布尔值>;

部分更新类型的类型相等

为什么ESLint会抱怨函数调用返回的隐式`any`?

如何编辑切片器以使用CRUD调用函数?

react 路由不响应参数

TypeScrip:如何缩小具有联合类型属性的对象

两个名称不同的相同打字界面-如何使其干燥/避免重复?

T的typeof键的Typescript定义

如何在Vuetify 3中导入TypeScript类型?

React中的效果挂钩在依赖项更新后不会重新执行

Typescript 和 Rust 中跨平台的位移数字不一致

如何按成员资格排除或 Select 元组?

使用本机 Promise 覆盖 WinJS Promise 作为 Chrome 扩展内容脚本?

如何确定单元格中的块对 mat-h​​eader-cell 的粘附(粘性)?

使用 TypeScript 在 SolidJS 中绘制 D3 力图