Как использовать тип параметра функции в Typescript?

#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] .