You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:36:04