Как вызвать метод по имени с разными подписями в Typescript? - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь настроить метод, который вызывает мой бэкэнд и делает для меня общие вещи.

Итак, я прихожу к этому коду:

myFct() {
    this[type](url, params, options).pipe(...)
}

get<T>(url: string, params: HttpParams, options: any): Observable<HttpEvent<T>> {
    return this._http.get<T>(url, options);
}

post<T>(url: string, params: HttpParams, options: any): Observable<HttpEvent<T>> {
    return this._http.post<T>(url, params, options);
}

put<T>(url: string, params: HttpParams, options: any): Observable<HttpEvent<T>> {
    return this._http.put<T>(url, params, options);
}

delete<T>(url: string, params: HttpParams, options: any): Observable<HttpEvent<T>> {
    return this._http.delete<T>(url, options);
}

Но я обнаружил, что метод 4 является избыточным, и я хотел бы знать, есть ли способ сделать это напрямую:

this._http[type](url, params, options)

Но я получаю эту ошибку:

Cannot invoke an expression whose type lacks a call signature

Поскольку GET и DELETE не имеют HttpParams в своей подписи.

Это способ, которым я могу вернуть параметры в зависимости от условия? Или вернуть два параметра и они совпадают с подписью?

Ответы [ 3 ]

0 голосов
/ 27 апреля 2018

Вы можете комбинировать помощника, который захватывает тип, объединение объявлений и сопоставленные типы для достижения желаемого эффекта. К сожалению

type Method = 'post' | 'put' | 'delete' | 'get';

type R = {
    [M in Method]: (this: { http: HttpClient }, method: M) => typeof this['http'][M]
};

interface MyHttp extends R { }

class MyHttp {
    constructor(http: HttpClient) {
        Object.assign(
          this, (<Method[]>['get', 'post', 'put', 'delete'])
            .map(method => http[method].bind(http))
        );
    }
}
0 голосов
/ 28 апреля 2018

Я считаю, что использование перегрузок функций даст то, что вы хотите:

myFct<T>(type: "get" | "delete", url: string, options: any): Observable<HttpEvent<T>>;
myFct<T>(type: "post" | "put", url: string, params: HttpParams, options: any): Observable<HttpEvent<T>>;
myFct<T>(type: "get" | "delete" | "post" | "put", url: string, paramsOrOptions: HttpParams | any, options?: any): Observable<HttpEvent<T>> {
    return type == "get" || type == "delete"
        ? this._http[type](url, paramsOrOptions)
        : this._http[type](url, paramsOrOptions, options) 
}


http.myFct<any>("get", "http://", {}) // OK
http.myFct<any>("get", "http://", {}, {}) // Error (too many args)
http.myFct<any>("post", "http://", {}, {}) // OK
http.myFct<any>("post", "http://", {}) // Error (too few args)

Хотя лично я не уверен, что это лучше, чем просто иметь 4 функции.

0 голосов
/ 27 апреля 2018

Вы можете использовать тот факт, что свойство .length функции возвращает количество аргументов, которое она принимает, и выполните:

(this._http[type].length === 3 ? 
    this._http[type](url, params, options) : 
    this._http[type](url, options));
...