TS2352错误:如何避免gRPC proto类型转换时使用unknown断言
问题根因
你的类型不匹配报错来自Observable泛型定义错误:
- 你将
testData$声明为Observable<TestReply>(对应proto生成的TestReply类实例类型) - 但你在service的stream data回调中,实际emit的是
message.toObject()的返回值,根据proto生成的类型定义,TestReply.toObject()方法返回的是TestReply.AsObject普通对象类型,而非TestReply类实例 - 你强行将
AsObject类型的值转成TestReply类类型,后续在组件中又要转回去,自然会触发类型不兼容报错
解决方案(两种可选,按需选用)
方案1:直接返回AsObject类型(推荐,如果你不需要调用TestReply类的实例方法)
修改Service.ts
@Injectable() export class ApiMyTestService { client: GrpcMyTestServiceClient; // 改泛型为AsObject类型 public readonly testData$: Observable<TestReply.AsObject>; constructor(private readonly http: HttpClient) { this.client = new GrpcMyTestServiceClient(environment.apiProxyUri); this.testData$ = this.listCoreStream(); } // 修改返回值泛型 listCoreStream(): Observable <TestReply.AsObject> { return new Observable(obs => { const req = new SomeRequest(); req.setClientName("GrpcWebTestClient"); const stream = this.client.getCoreUpdates(req); stream.on('status', (status: Status) => { console.log('ApiService.getStream.status', status); }); stream.on('data', (message: TestReply) => { // 这里message本身就是TestReply类实例,toObject直接返回对应类型,不需要强转 const asObject = message.toObject(); console.log('ApiService.getStream.data', asObject); obs.next(asObject); }); stream.on('end', () => { console.log('ApiService.getStream.end'); obs.complete(); }); }); }
修改Component.ts
export class AppComponent implements AfterViewInit, OnDestroy { // 这里如果不需要存TestReply类实例,可以改成TestReply.AsObject类型 public testReply?: TestReply.AsObject; public coreData? : TestReplyWithData.AsObject[]; private _subscription: Subscription; constructor(private readonly _MyTestService: ApiMyTestService) { this._subscription = new Subscription(); } public ngAfterViewInit(): void { this._subscription = this._MyTestService.testData$.subscribe((data) => { this.testReply = data; if (data) { // 不再需要任何类型转换,直接取属性即可 this.coreData = data.coreWithDataList; } }); }
方案2:保留TestReply类实例(如果你需要调用类上的方法,比如getCoreWithDataList等)
修改Service.ts的data回调
stream.on('data', (message: TestReply) => { // 直接emit TestReply类实例,不调用toObject obs.next(message); });
修改Component.ts逻辑
this._subscription = this._MyTestService.testData$.subscribe((data) => { this.testReply = data; if (data) { // 直接调用实例的toObject方法,返回的就是TestReply.AsObject类型,不需要转unknown this.coreData = data.toObject().coreWithDataList; // 或者也可以直接调用类的get方法: // this.coreData = data.getCoreWithDataList().map(item => item.toObject()); } });
内容的提问来源于stack exchange,提问作者mv_05
相关产品推荐
相关产品推荐

