Angular中TypeScript处理HTTP响应JSON时触发TS7053类型报错的解决方法求助
大家好,我在Angular项目里遇到了一个TypeScript类型检查的问题,想请教下怎么解决。
我写了一个调用后端接口的服务函数:
requestLabel(item_sit_id: bigint, type: string) { const uri = this.config.apiHost() + '/living/requestLabel/' + item_sit_id + "?type=" + type; const obs = this.http.get(uri) return obs; }
然后在组件里调用这个函数:
label(item_sit_id: string) { const that = this; this.livingService.requestLabel(this.feature.properties.item_sit_id, this.type).subscribe(function (jsonData) { const message = jsonData['success'] ? 'successful' : jsonData['message']; that.snackBar.open(message, 'Label request', { duration: 2000 }); }); this.bottomSheetRef.dismiss(); }
功能是正常工作的,但IntelliJ一直给jsonData['success']和jsonData['message']标红报错:
TS7053: Element implicitly has an any type because expression of type 'success' can't be used to index type Object
Property 'success' does not exist on type 'Object'
我知道这是TypeScript的类型检查导致的,因为默认http.get返回的是Object类型,没办法直接用字符串索引访问属性。想请教下有哪些优雅的解决方式?
下面分享几种常见的解决思路:
定义响应类型接口(最推荐):先定义一个接口来描述后端返回的JSON结构,让TypeScript准确推断类型,还能获得代码提示
// 先定义对应后端返回结构的接口 interface LabelResponse { success: boolean; message?: string; // 可以补充其他返回字段 } // 修改服务中的请求函数,指定返回类型 requestLabel(item_sit_id: bigint, type: string): Observable<LabelResponse> { const uri = this.config.apiHost() + '/living/requestLabel/' + item_sit_id + "?type=" + type; return this.http.get<LabelResponse>(uri); }这样订阅时
jsonData会自动被推断为LabelResponse类型,访问success和message就不会报错了。临时断言为any类型(快速解决但不推荐):如果只是想临时跳过类型检查,可以把
jsonData断言为any,但会失去TypeScript的类型保护优势this.livingService.requestLabel(...).subscribe(function (jsonData: any) { const message = jsonData['success'] ? 'successful' : jsonData['message']; // ...后续逻辑 });使用Record类型断言(比any更安全):如果不确定具体字段,但知道是键值对结构,可以用
Record<string, unknown>来断言,访问时再做类型缩小this.livingService.requestLabel(...).subscribe(function (jsonData: Record<string, unknown>) { const success = jsonData['success'] as boolean; const message = jsonData['message'] as string; const msg = success ? 'successful' : message; // ...后续逻辑 });
另外顺便提个小优化:组件代码里可以用箭头函数代替const that = this,这样能直接访问组件的this,代码更简洁:
label(item_sit_id: string) { this.livingService.requestLabel(this.feature.properties.item_sit_id, this.type).subscribe((jsonData) => { const message = jsonData.success ? 'successful' : jsonData.message; this.snackBar.open(message, 'Label request', { duration: 2000 }); }); this.bottomSheetRef.dismiss(); }
备注:内容来源于stack exchange,提问作者xpusostomos

