如何避免在带有mocha和未定义返回的TypeScript中使用if/else?

如何避免在带有mocha和未定义返回的TypeScript中使用if/else?,typescript,mocha.js,chai,Typescript,Mocha.js,Chai,可以网格化并返回另一条样条线的样条线。至少大多数时候是这样 导出默认类样条曲线{ 公共网络计数:数字; 构造函数(父?:样条线){ this.netictedcount=parent&&parent.netictedcount+1 | | 0; } 公共网状():样条线|未定义{ 返回新样条曲线(此); } } import{assert,expect}来自'chai'; 从“../src/Spline”导入样条曲线; 描述(“样条曲线”,()=>{ 常量样条=新样条(); 它(“返回一条新样

可以网格化并返回另一条样条线的样条线。至少大多数时候是这样

导出默认类样条曲线{
公共网络计数:数字;
构造函数(父?:样条线){
this.netictedcount=parent&&parent.netictedcount+1 | | 0;
}
公共网状():样条线|未定义{
返回新样条曲线(此);
}
}
import{assert,expect}来自'chai';
从“../src/Spline”导入样条曲线;
描述(“样条曲线”,()=>{
常量样条=新样条();
它(“返回一条新样条线”,()=>{
常量网状样条线=样条线。网状();
expect(网状样条曲线).to.not.be.null;
expect(网状样条线.网状计数).to.eq(1);
});
});
失败,错误TS2532:对象可能是“未定义的”。

/Users/dblock/source/ts/typescript-mocha/node_modules/ts-node/src/index.ts:245
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
test/spline.spec.ts:18:12 - error TS2532: Object is possibly 'undefined'.

18     expect(reticulatedSpline.reticulatedCount).to.eq(1);
解决方法是测试中的反模式,即
if

it(“返回新样条线”,()=>{
常量网状样条线=样条线。网状();
if(网状样条曲线){
expect(网状样条线.网状计数).to.eq(1);
}否则{
expect(网状样条曲线).to.not.be.null;
}
});
如果不禁用
strictNullChecks
,如何解决此问题


输入代码。

您可以使用非空操作符(

it("always can be reticulated again", () => {
  const reticulatedSpline = spline.reticulate();
  expect(reticulatedSpline).to.not.be.null;
  expect(reticulatedSpline!.reticulatedCount).to.eq(1);
});
正如文件所说:

在类型检查器无法得出结论的上下文中,可以使用[You]断言其操作数为非null和非未定义


因为
.to.not.be.null
不会影响这些示例中的代码流,TS当前无法推断它对传递给它的参数进行了更改。有一种依赖于代码流的方法可以使用

函数assertNotNull(v:T | null):v不可为null{
如果(!v)抛出新错误();
返回真值
}
declare const maybeAString:string |未定义
函数ex(){
//不起作用,因为TS无法知道这将抛出
assertNotNull(可能是字符串)
梅比斯林
//控制流分析知道此函数将验证maybeAString是否绝对不为null
if(assertNotNull(maybeAString)){
maybeAString//现在肯定是字符串
}
//控制流分析知道maybeAString不为null(aka为null)的分支返回,因此主路径必须为非null
如果(!assertNotNull(maybeAString))返回
maybeAString//现在肯定是字符串
}

更新了Typescript 3.7的示例,该示例引入了“断言签名”:

/**
*用以代替'expect(value).to.exist`
*
*解决TypeScript的控制流分析无法识别的Chai断言。
*@param{any}值
*/
导出函数expectToExist(值:T):断言值不可为null{
期望(价值)存在;
如果(值===null | |值===未定义){
抛出新错误(“预期值存在”);
}
}
参考文献:


是的,但这不是必需的。我想表达我的问题的另一种方式是如何使
expect(网状样条线).to.not.be.null
就TypeScript而言,如果
表现得像一个
,和/或帮助typechecker检测到这一点?好的,那么您希望发生的是不需要修改行
expect(网状样条线.网状计数).to.eq(1)因为您已经用前面的断言验证了
网状样条曲线
不为空。因为如果是这种情况,那么问题是编译器无法从断言中推断出这一点。你必须设法帮助它。您可以使用
非空
运算符或将
网状样条线
变量类型转换为样条线,并将
网状样条线作为样条线
。为什么它不能推断出它?断言最终在
null
上引发异常。这是对TS的bug/feature请求吗?我说它不能推断它,因为谁的断言是以它的方式执行的
mocha
。但是你可以提出它,尽管我不认为它会飞起来。因此,目前的选择是将
const网状样条线=spline.networkite()作为样条线来使用
或显式检查,定义一个助手:``函数expectNotNull(值:any){if(值){return value;}else{expect(值).to.not.be.null;}}}}``并将其与
const-networkedspline=expectNotNull(spline.networkite())一起使用。我认为这个答案(使用
)是迄今为止最优雅的。不太喜欢变通方法,但这似乎是一个特别干净的答案。干得好!
function assertNotNull<T>(v: T | null): v is NonNullable<T> {
    if (!v) throw new Error();
    return true
}

declare const maybeAString: string | undefined

function ex() {
    // Doesn't work because TS has no way to know that this will throw
    assertNotNull(maybeAString)
    maybeAString

    // Control flow analysis knows that this function will validate that maybeAString is definitely not null
    if(assertNotNull(maybeAString)) {
        maybeAString // now definitely a string
    }

    // control flow analysis knows that the branch where maybeAString isn't not null (aka is null) returns, so the main path must be non-null
    if(!assertNotNull(maybeAString)) return

    maybeAString // now definitely a string
}