strictNullChecks和空值传播

时间:2019-07-24 08:10:59

标签: typescript

我想在很大的代码库中开始使用strictNullChecks标志。这绝对是一个非常有用的标志,但是我开始在大多数接口定义中包括null类型。也许这是个人的看法,因为我以前从未使用过该标志,但是它开始降低了代码的可读性(imho)。我有空无处不在的感觉。所有这些都源自返回<type> | null的函数,该函数在函数调用堆栈中向上传播,迫使我在接口中也包含空类型。

大多数时候,我都有可选的可为空字段,例如:

interface X {
  field?: string | null
}

当null和undefined都是伪造的值时,这种事情有点奇怪。

我曾考虑过用未定义的空类型替换空类型,例如:<type> | undefined从可选的接口字段中删除空类型,所以我只有:

interface X {
  field?: string
}

但是后来我失去了null的语义值,这是我想要维护的。

那么,您如何看待strictNullChecks?您是否发现这类字段field?: string | null有点怪异,还是您喜欢并感到满意?

2 个答案:

答案 0 :(得分:2)

我个人建议完全删除null,而改用undefined

如果您的应用程序中nullundefined值之间存在语义差异,则可能会引起混淆(在TS和纯JS中)。如果您不这样做,而您只是随机返回null / undefined,则只使用其中一个会更简单,更一致。

就使用哪种方式而言,我建议使用undefined,主要是因为TypeScript对它的支持更好一些(即?)。有一些参数仅使用null来代替,它更加冗长,并且使用undefined作为丢失数据的指示符通常很方便,因为它是每个未初始化变量/字段的默认值,而那些< em>应该通常具有与明显不可用的数据相同的语义和行为。

答案 1 :(得分:0)

我同意蒂姆·佩里(Tim Perry)的回答,即只使用一个-null或undefined-我的建议还坚持使用undefined,主要是因为您无法避免,因为这是缺少字段和未初始化的值变量。

对于默认函数参数,null也无效:

function f(x = 1) {
  // ...
}

这里f(undefined)会将x设置为1,但是f(null)不会!

null的唯一参数是JSON不支持显式undefined,但这不是像当您反序列化需要显式null值(而不是缺少值,实际上意味着未定义)的JSON时那样的问题。可以轻松地将其转换。

在我的项目中,我尽量使用linter配置禁止空值,例如对于TSLint:

    "no-any": true,
    "no-null-keyword": true

这个女巫strictNullChecks可以很好地避免多种错误。

请记住,NULL的创建者称其为十亿美元的错误。具有两个无效值甚至更糟。但是,如果您只有一个(如未定义),并且在TypeScript中使用严格的null检查,那么可以避免大多数语言通常由null / undefined引起的问题。

无论您要使用undefined,null还是同时使用这两者,我都强烈建议您始终使用strictNullChecks,因为没有它,您的代码就不是真正的安全类型。

有关TypeScript 2.0 release notes的有关null和undefined的类型的信息,请参见:

  

类型检查器以前认为是null,并且未定义可分配给任何内容。实际上,null和undefined是每种类型的有效值,因此不可能专门排除它们(因此无法检测到对它们的错误使用)。 [强调]

默认情况下未启用该功能,以便与添加新的检查null和undefined的方法之前编写的旧代码向后兼容。

考虑以下简单功能:

const f = (x: string) => x.toLowerCase();

没有严格的标志,输入安全。 使用运行时TypeError异常,它可能崩溃

  

TypeError: Cannot read property 'toLowerCase' of undefined

带有严格标志:

const f = (x: string | null) => x.toLowerCase(); // COMPILE TIME ERROR
const f = (x: string | null) => x && x.toLowerCase(); // OK and safe

有关更多信息,请参见: