Mostafa Saadatnia
Mostafa Saadatnia

Reputation: 878

overwrite function in typescript inheritance

I have a class bellow:

  export class RestService {

  private baseUrl: string;

  constructor(protected http: HttpClient) {
    this.baseUrl = environment.LOCAL_URL;
  }

  public get<T>(resource: string, params?: HttpParams): Observable<T> {
    const url = this.PrepareUrl(resource);
    return this.http.get<T>(url, { params }).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  public post<T>(resource: string, model: any): Observable<T> {
    const url = this.PrepareUrl(resource);
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    return this.http.post<T>(url, model, { headers }).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  public put<T>(resource: string, model: any): Observable<T> {
    const url = this.PrepareUrl(resource);
    return this.http.put<T>(url, model).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  public delete(resource: string, id: any): Observable<any> {
    const url = this.PrepareUrl(resource) + `\\${id}`;
    return this.http.delete(url).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  protected PrepareUrl(resource: string): string {
    return `${this.baseUrl}/${resource}`;
  }

  protected catchBadResponse(error: HttpErrorResponse) {
    console.log('error occured!');
    return throwError(error);
  }
}

and another class that extends RestService class:

export class PersonRestService extends RestService {

  constructor(protected http: HttpClient) {
    super(http);

  }
  public get<T>(params?: HttpParams): Observable<T> {
    return super.get<T>('person', params);
  }

  public post<T>(model: any): Observable<T> {
    return super.post('person', model);
  }
}

i want to override some functions in the child class but i have this hint(error) from ide:

Property 'get' in type 'PersonRestService' is not assignable to the same property in base type 'RestService'. Type '(params?: HttpParams) => Observable' is not assignable to type '(resource: string, params?: HttpParams) => Observable'. Types of parameters 'params' and 'resource' are incompatible. Type 'string' is not assignable to type 'HttpParams'.ts(2416)

What should i do?

Upvotes: 1

Views: 1484

Answers (2)

Mostafa Saadatnia
Mostafa Saadatnia

Reputation: 878

in typescript we cannot overwrite the methods 100%;like this problem that we cannot overwrite the legacy methods. there is a qoute says: "Favor Composition Is Over Inheritance'; so I change the code snippets like this bellow:

1-Don't change the RestService:

export class RestService {

  private baseUrl: string;

  constructor(protected http: HttpClient) {
    this.baseUrl = environment.LOCAL_URL;
  }

  public get<T>(resource: string, params?: HttpParams): Observable<T> {
    const url = this.PrepareUrl(resource);
    return this.http.get<T>(url, { params }).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  public post<T>(resource: string, model: any): Observable<T> {
    const url = this.PrepareUrl(resource);
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    return this.http.post<T>(url, model, { headers }).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  public put<T>(resource: string, model: any): Observable<T> {
    const url = this.PrepareUrl(resource);
    return this.http.put<T>(url, model).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  public delete(resource: string, id: any): Observable<any> {
    const url = this.PrepareUrl(resource) + `\\${id}`;
    return this.http.delete(url).pipe(
      retry(2),
      catchError(this.catchBadResponse)
    );
  }

  protected PrepareUrl(resource: string): string {
    return `${this.baseUrl}/${resource}`;
  }

  protected catchBadResponse(error: HttpErrorResponse) {
    console.log('error occured!');
    return throwError(error);
  }
}

2-Remove extending in PersonRestService form RestService and Inject RestService in the constructor:

export class PersonRestService {

  constructor(private restService: RestService) {
  }
  public get<T>(params?: HttpParams): Observable<T> {
    return this.restService.get<T>('person', params);
  }
}

Done! now I can play with code.

Upvotes: 1

Athanasios Kataras
Athanasios Kataras

Reputation: 26432

Seems like you've hit the following bug.

For now you can do one of the two things:

  1. Change your signature to match it 100%

    public get(resource: string, params?: HttpParams): Observable { return super.get('person', params); }

Or to make it a little better, change the order and make it optional:

public get<T>(params?: HttpParams, resource: string = ''): Observable<T> {
    return super.get<T>(params,'person');  
  }
  1. Remove the generic from the PersonRestService class.

The second one makes more sense to me. You know that your resource is a Person so you could do it like this:

  public getPerson(params?: HttpParams): Observable<object> {
    return super.get<object>(params,'person');  
  }

Upvotes: 1

Related Questions