One important strategy that has not been included in any of the answers is to use interfaces to mine API/service response data structure contracts/expectations, facilitating identification of data structure mismatches between front-end vs back-end expectations of what the structure should be.
If your app uses asynchronous service/API requests, you will not be able to use interfaces directly to catch errors during compile time b/c the compiler does not know what the responses for each async request are. If no errors are thrown, you may never detect data type discrepancies.
However, if have a well-defined unit test suite that uses test data of type <interface-name>, Jasmine and Jest will catch any mismatches between your test data's structure and what the structure should be according to the interface. IMO this is an incredibly useful way of data-mining your service-endpoint/API responses to help ensure the front-end and back-end expectations of the structure of the data is in sync. This is especially important on larger projects which have multiple developers, or even multiple teams,working on different tasks. In my experience it is very common that the structures of data models become out-of-sync in these cases; team turnover and lack of documentation are prime culprits here.
You can simply copy objects from REAL service/API responses and use those as test data in your unit tests.
So let's say in your component:
this.service.getData()
.pipe(...)
.subscribe((resp: dataInterface[]) => {
this.allData = resp;
});
... and suppose you have a spec.ts that loads its component with mockResponse:
const mockResponse: dataInterface[] = [
{
a: "test1",
b: "test2"
}, ...
];
where
export interface dataInterface {
a: string;
b: string;
}
.....
providers: [
{
provide: ServiceRequest,
useValue: {
getData: () => of(mockResponse)
}
}
], ...
then this unit test will pass:
expect(component.allData).toEqual(mockResponse);
Now suppose over time, with team turnover, a newer team member - seeing no issues with the edit or no corrections in a pull request - changes the interface to
export interface dataInterface {
a: string;
// 'b' is removed b/c developer sees nothing break in the UI with its removal
}
If the IDE doesn't flag this and get the developer's attention, the Jasmine compiler will.
Here is a screenshot from our team's app where an interface called caseDetail was expecting a property called groupName. I had copied the service response directly from a real request's response and copied into my unit test. When I tried to run the test suite, the Jasmine compiler flagged the test data as missing this property:

It's possible that this discrepancy would otherwise never have been caught, since no functionality on our app actually broke b/c groupName was missing in the response. I was then able to go back to our backend devs and create a spike to explore this discrepancy.