У реализации должна быть наиболее общая сигнатура от всех перегрузок. Притом типы в реализации работают только внутрь, а наружу торчат только перегрузки:
export class MyHttpClient {
constructor(private readonly http: HttpClient) {}
put(params: Params<'body', 'arraybuffer'>): Observable<ArrayBuffer>;
put(params: Params<'body', 'blob'>): Observable<Blob>;
put(params: Params<'body', 'text'>): Observable<string>;
put(params: Params<'events', 'arraybuffer'>): Observable<HttpEvent<ArrayBuffer>>;
put(params: Params<'events', 'blob'>): Observable<HttpEvent<Blob>>;
put(params: Params<'events', 'text'>): Observable<HttpEvent<string>>;
put(params: Params<'events', 'json'>): Observable<HttpEvent<Object>>;
put<T>(params: Params<'events', 'json'>): Observable<HttpEvent<T>>;
put(params: Params<'response', 'arraybuffer'>): Observable<HttpResponse<ArrayBuffer>>;
put(params: Params<'response', 'blob'>): Observable<HttpResponse<Blob>>;
put(params: Params<'response', 'text'>): Observable<HttpResponse<string>>;
put(params: Params<'response', 'json'>): Observable<HttpResponse<Object>>;
put<T>(params: Params<'response', 'json'>): Observable<HttpResponse<T>>;
put(params: Params<'body', 'json'>): Observable<Object>;
put(params: Params<Observe, ResponseType>): Observable<unknown> {
return this.http.put(params.url, params.body, params.options as Params<'body', 'json'>['options']);
}
}
А вообще, мне почему-то кажется, что так будет гораздо проще:
type ResponseTypeMap = {
arraybuffer: ArrayBuffer;
blob: Blob;
text: string;
json: Object;
};
type ResponseTypes = keyof ResponseTypeMap;
type ObserveWrapperMap<T extends ResponseTypeMap[ResponseTypes]> = {
body: Observable<T>;
events: Observable<HttpEvent<T>>;
response: Observable<HttpResponse<T>>;
};
type ObserveWrappers = keyof ObserveWrapperMap<ResponseTypeMap[ResponseTypes]>;
type Result<O extends ObserveWrappers, R extends ResponseTypes> = ObserveWrapperMap<ResponseTypeMap[R]>[O];
type Params<O extends ObserveWrappers, R extends ResponseTypes> = {
url: string;
body: any;
options?: {
headers?: HttpHeaders | Record<string, string | string[]>;
observe?: O;
params?: HttpParams | Record<string, string | string[]>;
reportProgress?: boolean;
responseType: R;
withCredentials?: boolean;
};
}
export class MyHttpClient {
constructor(private readonly http: HttpClient) {}
put<O extends ObserveWrappers = 'body', R extends ResponseTypes = 'json'>(params: Params<O, R>): Result<O, R> {
const {url, body, options} = params as Params<'body', 'json'>;
return this.http.put(url, body, options) as Result<O, R>;
}
}
особенно если помимо put будут и другие методы