如何让TypeScript在子代码块中延续已校验的类型?
解决TypeScript异步回调中类型守卫失效的问题
TypeScript的类型守卫窄化效果仅在当前作用域有效,异步回调(如then/finally内的函数)属于独立作用域,编译器无法保证回调执行时this.loadMoreData的类型与之前校验的一致,因此会抛出类型错误。以下是几种可行的解决方法:
方法1:将校验后的变量存入局部变量(推荐)
把this.loadMoreData赋值给局部变量,局部变量的类型窄化会被TypeScript捕获,回调中引用该变量即可保留正确类型:
if (isSingle(this.loadMoreData)) { // 存入局部变量,保留LoadMoreData类型 const loadMoreData = this.loadMoreData; loadMoreData.blockAction = true; this._fetchData() .then(r => { if (r === false) { loadMoreData.finishedData = true; } if (r !== null && r !== undefined) { loadMoreData.isFirst = false; } }).finally(() => { loadMoreData.blockAction = false; loadMoreData.mainLoading = false; this.cdr.detectChanges(); }); } else { // 处理LoadMoreDataGroup类型的逻辑 }
方法2:使用类型断言
若能确保异步操作期间this.loadMoreData的类型不会改变,可在回调中手动用类型断言指定类型:
if (isSingle(this.loadMoreData)) { this.loadMoreData.blockAction = true; this._fetchData() .then(r => { // 手动断言为LoadMoreData类型 const data = this.loadMoreData as LoadMoreData; if (r === false) { data.finishedData = true; } if (r !== null && r !== undefined) { data.isFirst = false; } }).finally(() => { const data = this.loadMoreData as LoadMoreData; data.blockAction = false; data.mainLoading = false; this.cdr.detectChanges(); }); } else { // 处理LoadMoreDataGroup类型的逻辑 }
方法3:在回调中重新执行类型校验
若需保证类型安全(比如担心异步期间变量被修改),可在回调内再次调用isSingle进行校验:
if (isSingle(this.loadMoreData)) { this.loadMoreData.blockAction = true; this._fetchData() .then(r => { // 再次校验类型 if (isSingle(this.loadMoreData)) { if (r === false) { this.loadMoreData.finishedData = true; } if (r !== null && r !== undefined) { this.loadMoreData.isFirst = false; } } }).finally(() => { if (isSingle(this.loadMoreData)) { this.loadMoreData.blockAction = false; this.loadMoreData.mainLoading = false; this.cdr.detectChanges(); } }); } else { // 处理LoadMoreDataGroup类型的逻辑 }
内容的提问来源于stack exchange,提问作者Hossein Rajabi
相关产品推荐
相关产品推荐

