There are two approaches depending on if you want your interceptor to require "proper" inheritance of the body or if it's enough for the body to have the right shape (see duck typing).
Typescript types don't exist at runtime, so if you want proper inheritance, you'll have to rely on JavaScript's prototype chain. This is handled for you by the extends
keyword so long as you use the constructor(s) of the base/derived class(es).
class Base {
constructor(commonProperty) {
this.commonProperty = commonProperty;
}
}
class Derived extends Base {
constructor() { super('derived'); }
}
// Using constructors allows for checking
// inheritance by prototype chain.
const foo = new Derived();
console.log(foo instanceof Base); // true
// Objects that look like derived instances
// are not necessarily derived instances
// (duck typing is not inheritance).
const bar = { commonProperty: 'not derived' };
console.log(bar instanceof Base); // false
If you require proper inheritance, I think you should be able to do this with the vanilla instanceof
operator since AbstractMyModel.prototype
should show up in the prototype chain for any class Foo extends AbstractMyModel
.
Set up an interceptor as usual, check the method and body of the request it receives, then perform whatever logic you need.
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { AbstractMyModel, transformFn } from '../models/abstract-my.model';
const supportedMethods = ['PUT', 'POST'];
export class MyModelInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// Short circuit if the request doesn't match
// our criteria.
const methodUnsupported = !supportedMethods.some(m => request.method === m);
const bodyTypeUnsupported = !(request.body instanceof AbstractMyModel);
if (methodUnsupported || bodyTypeUnsupported) {
return next.handle(request);
}
// Otherwise perform whatever logic we need.
const commonProperty = transformFn(request.body.commonProperty);
const newBody = { ...request.body, commonProperty };
const newRequest = request.clone({ body: newBody });
return next.handle(newRequest);
}
}
If the shape of the body is sufficient (you don't need instance methods provided by AbstractMyModel
), you can check for the existence of the property you care about.
Again, there are two ways: Object.hasOwnProperty()
or the in
operator and the difference is discussed in this question: "if (key in object) or if(object.hasOwnProperty(key)". In this case, you want 'commonProperty' in request.body
since the object doesn't need to have its own copy of commonProperty
- an inherited version is sufficient.
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { AbstractMyModel, transformFn } from '../models/abstract-my.model';
const supportedMethods = ['PUT', 'POST'];
export class MyModelInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// Short circuit if the request doesn't match
// our criteria.
const methodUnsupported = !supportedMethods.some(m => request.method === m);
const bodyTypeUnsupported = !('commonProperty' in request.body);
if (methodUnsupported || bodyTypeUnsupported) {
return next.handle(request);
}
// Otherwise perform whatever logic we need.
const commonProperty = transformFn(request.body.commonProperty);
const newBody = { ...request.body, commonProperty };
const newRequest = request.clone({ body: newBody });
return next.handle(newRequest);
}
}