tl; dr:我希望能够使用assert
实用程序来检查值是否为非空,然后让Typescript理解该值是否为非空。我已启用strictNullChecks
,并且我不想使用非null断言运算符。
根据the typescript docs,我可以使用断言的一种方法是使用非空断言运算符(从文档稍作修改):
// Compiled with --strictNullChecks
function assertEntity(e?: Entity) {
// Throw exception if e is null or undefined
}
function processEntity(e?: Entity) {
assertEntity(e);
let s = e!.name; // Assert that e is non-null and access name
}
但是,我更喜欢不经常使用断言,因为它们容易被滥用。我宁愿做这样的事情:
// Add a good return type to assertEntity to clarify that it may throw
function assertEntity(e?: Entity): void | never {
if (!e) {
throw Error('Entity is falsy!');
}
}
function processEntity(e?: Entity) {
assertEntity(e);
// At this point I'd like typescript to know that e is truthy
let s = e.name;
}
文档说,非空断言运算符将在“类型检查器无法得出该事实的地方”使用。我的问题是,有什么办法可以帮助类型检查器正确得出e
不为空的结论?
我已经知道执行此操作的几种方法,这些方法比我想要的要多一些。例如,我可以使用user-defined type guard,但这可能导致缩进级别更高:
function checkEntity(e: any): e is Entity {
return e && e.name;
}
function processEntity(e?: Entity) {
assertEntity(e);
// This checkEntity call seems superfluous, since I'm already
// calling assertEntity above.
if (checkEntity(e)) {
let s = e.name;
}
}
或者我可以用不同的方式来做到这一点,这也解决了类型问题,但是由于它具有虚假的早期返回,因此需要一些误导性代码:
// Note that assertEntity is now a user-defined type guard, because of
// the `e is Entity` return value.
function assertEntity(e?: Entity): e is Entity {
if (!e) {
throw Error('Entity is falsy!');
}
return true;
}
function processEntity(e?: Entity) {
// I can make assertEntity into a user-defined type guard, but then this
// code looks as if it might have an early return, when in fact it will throw
// if `e` is falsy.
if (!assertEntity(e)) {
return; // This return is impossible to reach
}
let s = e.name;
}