我创建了一个类型防护,用于检查参数是否恰好是null
:
function isNotNull<T> (arg: T): arg is Exclude<T, null> {
return arg !== null
}
当我对其进行测试时,then
分支正常工作:它从类型中剥离了null
。
const value: string | null = 0 as any
if (isNotNull(value)) {
// value is of type `string` here
}
但是,它在never
分支中变成了else
。
const value: string | null = 0 as any
if (isNotNull(value)) {
// `value` is of type `string` here
} else {
// `value` is of type `never` here
}
我希望它在null
分支中解析为else
。
我该如何实现?
答案 0 :(得分:2)
这里的问题是作业:
const value: string | null = 0 as any
编译器知道value
是一个常量,因此它永远不能为null。
使用let
并不会变得更好:
let value: string | null = 'foo';
if (isNotNull(value)) {
// `value` is of type `string` here
} else {
// `value` is of type `never` here
}
再次,打字稿编译器知道该值不为空。
但是,如果分配一些Typescript无法推断恒定值的内容,那么您将在string
分支中拥有期望的if
,在null
中拥有else
:< / p>
function isNotNull<T> (arg: T): arg is Exclude<T, null> {
return arg !== null
}
let value: string | null = foo();
if (isNotNull(value)) {
// `value` is of type `string` here
} else {
// `value` is of type `null` here
}
function foo(): string | null {
return "foo"
}
此外,即使最后一个示例也仅在您将strictNullChecks
编译器选项设置为true时才有效。如果您尚未启用strictNullChecks
,则无法从null
中排除type
,并且if
分支将是string
,与string | null
相同因此,never
只剩下else
。
编辑:
当strictNullChecks
关闭时,此操作不起作用的原因非常有趣。在那种情况下,类型string | null
和string
是相同的。这意味着value
实际上具有类型string
,而Exclude<string, null>
只是string
(因此仍然包括null
),因此else
子句是左侧,类型为never
的类型为value
。