#angular #typescript
#angular #typescript
Вопрос:
Я оборачиваю службу HttpClient от Angular в свой собственный метод, но все еще хочу, чтобы пользователи могли передавать options
, однако, похоже, я не могу найти хороший способ ссылаться на этот тип в определении параметра моего собственного метода.
пример:
constructor(private http: HttpClient) {}
my_request<T = any>(endpoint: string, payload: T, options: WhatTypeHere = {}) {
return this.http.post<MyHttpResponse>(this.build_url(endpoint), this.build_payload(payload), {
...options,
withCredentials: true,
});
}
Вы можете увидеть options
параметр my_request()
Я не знаю, что я могу туда поместить, чтобы при использовании my_request он мог принудительно применять его.
Вот определение HttpClient.post()
к вашему сведению
post(url: string, body: any | null, options?: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
observe?: 'body';
params?: HttpParams | {
[param: string]: string | string[];
};
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<Object>;
Я знаю, что мог бы скопировать-вставить это определение целиком в свой метод, но если есть какой-то способ, которым я могу ссылаться на него, я бы предпочел для краткости и на случай, если определения изменятся в будущем.
Одна вещь, которую я пробовал, но которая не сработала, была чем-то вроде options: HttpClient['post']['options']
Есть ли что-нибудь подобное, что я могу использовать для ссылки на этот тип?
Комментарии:
1. Вы пробовали использовать
interface
?2. Что вы имеете в виду? Нравится создавать мой собственный интерфейс, который отражает их определение? Я бы предпочел не идти этим путем.
3. Почему бы и нет? Я думаю, что это был бы ваш лучший вариант, точно так же, как вы ссылаетесь на непримитивные типы в typescript.
4. Две причины. Поскольку это определение взято из сторонней библиотеки, если я создам свой интерфейс и их определение изменится в какой-то момент, мне придется обновить свой интерфейс, и, вероятно, я забуду об этом, что вызовет проблемы в будущем. Кроме того, кажется излишним дважды использовать одно и то же определение. Вот почему я задал этот вопрос. Я знаю, что могу создать интерфейс, но я ищу другой вариант. Какой-нибудь способ напрямую ссылаться на их определение.
Ответ №1:
По крайней мере, в typescript 3.3 (версия на playground на момент написания) можно извлечь тип 3-го параметра post
. Смотрите урезанный пример ниже:
interface A {
eh: number
}
function post(url: string, body: any | null, options?: {a: A}): void {}
// Create an alias for convenience
type PostOptions = Parameters<typeof post>[2];
let options: PostOptions;
options = {}; // Expected error: Property 'a' is missing in type '{}' but required in type '{ a: A; }'.
options = { a: {} }; // Expected error: Property 'eh' is missing in type '{}' but required in type 'A'.
options = {a: {eh: 10}} // Ahh... just right :)
<a rel="noreferrer noopener nofollow" href="https:///www.typescriptlang.org/play/#src=interface A {
eh: number
}
function post(url: string, body: any | null, options?: {a: A}): void {}
type PostOptions = Parameters[2];
let options: PostOptions;
options = {};
options = { a: {} };
options = {a: {eh: 10}}» rel=»nofollow noreferrer»>Ссылка на игровую площадку
Еще немного пояснений: Parameters<T>
это тип параметров функции T
в виде кортежа. typeof post
возвращает тип функции, а затем нам нужен третий параметр, который является типом в кортеже по индексу 2
.
Комментарии:
1. да, это именно то, что я искал. Спасибо! Смог использовать
Parameters<HttpClient['post']>[2]
.