0

Working on consuming a gRPC server stream call from Angular client. Getting below error type conversion error:

"Conversion of type 'TestReply' to type 'AsObject' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type 'TestReply' is missing the following properties from type 'AsObject': prop1, prop2, prop3.ts(2352)"

To solve this, I need to convert the type as unknown before converting to the desired type like

data as unknown as TestReply.AsObject

How to fix the above without using unknown conversion. Here is the full code snippet:

Service.ts

  @Injectable()
    export class ApiMyTestService {    
        client: GrpcMyTestServiceClient;
        public readonly testData$: Observable<TestReply>;
  
    constructor(private readonly http: HttpClient) {
        this.client = new GrpcMyTestServiceClient(environment.apiProxyUri);
        this.testData$ = this.listCoreStream();
    }
  
   listCoreStream(): Observable <TestReply> {
    return new Observable(obs => {      
      const req = new SomeRequest(); //not significant to the type conversion problem
      req.setClientName("GrpcWebTestClient");
      const stream = this.client.getCoreUpdates(req); // Main gRPC Server stream Api call 
      stream.on('status', (status: Status) => {
        console.log('ApiService.getStream.status', status);
      });
      stream.on('data', (message: any) => {
        // gRPC Api call returns stream data here
        console.log('ApiService.getStream.data', message.toObject());
        obs.next(message.toObject() as TestReply);
      });
      stream.on('end', () => {
        console.log('ApiService.getStream.end');
        obs.complete();        
      });     
    });
  }

Component.ts

export class AppComponent implements AfterViewInit, OnDestroy {   
   public testReply?: TestReply;
   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) {
               var dtr = data as unknown as TestReply.AsObject // How to get rid of unknown here?          
               this.coreData = dtr.coreWithDataList;            
            }
        });
}

Generated ts file from proto file showing the type definitions

export namespace TestReply {
      export type AsObject = {
        coreWithDataList: Array<TestReplyWithData.AsObject>,
      }
    }
export namespace TestReplyWithData {
  export type AsObject = {
    prop1: number,
    prop2: number,
    prop3: number,
    //more attributes (of primitive types)...
    }
}
    // Classes  - TestReply and TestReplyWithData are not significant to the type conversion problem
    export class TestReply extends jspb.Message {
        // There are more methods generated but specifying couple of methods below for simplicity
        getCoreWithDataList(): Array<TestReplyWithData>;
        toObject(includeInstance?: boolean): TestReply.AsObject;
    }
    
    export class TestReplyWithData extends jspb.Message {
        // There are more methods generated but specifying couple of methods below for simplicity
        toObject(includeInstance?: boolean): TestReplyWithData.AsObject;
        static toObject(includeInstance: boolean, msg: TestReplyWithData): TestReplyWithData.AsObject;
      }
mv_05
  • 109
  • 12
  • 1
    set type on your observable `public readonly testData$: Observable;`, and you won't need to convert it later – Andrei Sep 14 '21 at 09:14
  • Thank you @Andrei that worked :). Updated the return type to Observable instead of Observable in the service method and the public testData$ – mv_05 Sep 14 '21 at 21:57

0 Answers0