2

I have a .net core web api that returns a list of ethnicities with a number of properties. Using the angular httpclient I call the api and return the data. When I subscribe in angular and cast the data to a much more simple interface, the full object is mapped / cast. Not what I was expecting.

Here is what I have:

export interface IEthnicity {
    id: any;
    ethnicity: string;
}
export class AppComponent {
  ethnicities: IEthnicity[] = [];

  constructor(private svc: MyServiceService) {
    this.svc.getList().subscribe(
      resp =>{
        this.ethnicities = resp as IEthnicity[];
        console.log(this.ethnicities);
      }
    );
  }
}

I was expecting my ethnicities array to hold a list of the same type as the interface but it is an array with the same type as returned by the web api.

e.g.

0: {Id: 'abc1', OrganisationId: 'org1', Ethnicity: 'Indian', IsDeleted: false }
1: {Id: 'abc2', OrganisationId: 'org1', Ethnicity: 'White', IsDeleted: false }
2:
   Ethnicity: "Chinese"
   Id: "abc3"
   IsDeleted: false
   OrganisationId: "org2"
3: {Id: 'abc4', OrganisationId: 'org3', Ethnicity: 'Irish', IsDeleted: false }
4: {Id: 'abc5', OrganisationId: 'org2', Ethnicity: 'Arab', IsDeleted: false }

Notice the properties do not match the interface, The capitalisation of the first letter of the name of the property and the double quotes " instead of single quotes ' around the expanded array item values.

Regardless of what is actually coming back from the api, the resp as IEthnicity[] should cast the values to the two interface properties only. What am I missing?

Update

For anyone who has the same problem, a simple answer is to use the map function in rxjs. Don't forget to include the following import import { map } from 'rxjs';

    svc.getList().pipe(
      map((list: any) => list.map((ethnicity: any) => ({ id: ethnicity.Id, ethnicity: ethnicity.Ethnicity }) as IEthnicityType ))
    )
    .subscribe(
      data => {
        this.ethnicities = data as IEthnicityType[];
      }
    );

Hope this helps

  • 3
    TypeScript doesn't have "casting", or at least the term "casting" is so loaded as to be best avoided. TypeScript has [type assertions](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions), which is where you tell the compiler that an expression will actually be of some type, generally because the compiler can't figure that out itself. TypeScript's type system is (almost) completely erased; no type annotation, interface, assertion will survive to the emitted JavaScript. `foo as Bar` becomes just `foo` at runtime. – jcalz Feb 12 '22 at 00:49
  • See https://stackoverflow.com/questions/60218424/how-can-i-cast-or-change-the-generic-type-in-typescript – jcalz Feb 12 '22 at 00:51
  • I'm inclined to close this as a duplicate of the previous question, and of https://stackoverflow.com/questions/50839597/typescript-extract-interface-members-only-possible, and of https://stackoverflow.com/questions/63940196/casting-object-to-a-type-same-as-my-interface-in-typescript . If you want this question to remain open and get its own answer, please elaborate on what the difference is. – jcalz Feb 12 '22 at 02:10
  • 1
    I agree @jcalz, I have flagged as a duplicate. Thanks for pointing me in the right direction. I didn't realise the difference between the cast and assertion of this command before you explained. Thanks – zakilmsoftwarecom Feb 12 '22 at 10:44

0 Answers0