Можно ли установить значение по умолчанию для аргумента в машинописи, когда тип аргумента является универсальным? - PullRequest
3 голосов
/ 29 мая 2019

Я пишу универсальные методы, чтобы использовать их в различных приложениях веб-интерфейса, и идея состоит в том, чтобы иметь возможность вызывать функцию .postAsync<CustomModel>('www.mysite.com',..., CustomModel);, а предполагаемый ответ - объект CustomModel.

Я быхотелось бы иметь возможность установить значение по умолчанию для второго параметра, так что по умолчанию это будет другая модель, которую можно будет переопределить при необходимости.

Как установить значение по умолчанию для аргумента, которыйимеет тип Constructable<T>, где интерфейс Construable означает

interface Constructable<T> { new(params : any): T ;}

Я попытался установить значение по умолчанию для интерфейса, который принимает аргумент, и установить аргумент для различных типов, но я всегда получаю ошибку Type Constructable<CustomModel> is not assignable to type Constructable<T>.Я также установил тип T по умолчанию в методе, общем для CustomModel, а затем попробовал это и получил ту же ошибку.

interface Constructable<T> { new(params : any): T ;}


export default class WebapiBase {

    static async postAsync<T = CustomModel>(
        uri: string,
        body: object,
        headers: CustomHeaders = new CustomHeaders(),
        // This is the part giving errors
        model: Constructable<T> = <Constructable<CustomModel>>,): Promise<T> {
        return this.requestAsync<T>(model, HTTP_METHOD.POST, uri, headers, body);
    }

    private static async requestAsync<T>(
        model: Constructable<T>,
        method: HTTP_METHOD,
        uri: string,
        headers: CustomHeaders,
        body?: object): Promise<T> {
        const url = new URL(uri, window.location.origin);
        const request = this.buildRequest(url, method, headers, body);
        const bodyResponse = await fetch(request)
            .then(response => this.validate(response, request.headers))
            .then(validResponse => this.extractBody(validResponse))
            // Here is where the response body is being used to initialise one of the custom models that we are passing in. Code below
            .then(extractedBody => this.buildModel<T>(model, extractedBody))
            .catch((error) => { throw this.handleError(error); });
        return bodyResponse;
    }

    private static buildModel<T>(
        Model: Constructable<T>,
        params: ResponseBody,
    ): T {
        return new Model(params);
    }
}

Я ожидал, что мне не нужно будет передавать модель в метод postAsync() и что он всегда будет возвращать объект CustomModel.Но в действительности я получаю эту ошибку Type Constructable<CustomModel> is not assignable to type Constructable<T>

Пример на игровой площадке, наведите курсор мыши на Constructable в аргументах, чтобы увидеть ошибку

1 Ответ

0 голосов
/ 05 июля 2019

Я решил проблему, которая заключалась в возвращении значения по умолчанию (в данном случае универсального объекта) в случае, если модель не была передана.Как правило, исправления были следующие:

  • Вместо того, чтобы модель печаталась как интерфейс Constructable, но использовался тип объединения Constructable<T> | object.
  • .Модель передается в Object.
  • buildModel() Функция проверяет тип модели и, если это объект, возвращает передаваемые значения, если это конструируемый объект, а затем создает его экземпляр.

Узнайте, как это реализовано в параметрах postAsync, в интерфейсе ResponseModel и в методе buildModel, реализованном в requestAsync:

interface Constructable<T> { new(params : any): T ;}
type ResponseModel<T> = Constructable<T> | Object;

export default class WebapiBase {
  static async postAsync<T = Object>(
      {
          uri = '',
          body = {},
          headers = new CustomHeaders(),
      }: PostRequestParams = {},
      // Here is where the defualt is implemented
      model: ResponseModel<T> = Object): Promise<T> {
      return this.requestAsync(model, HTTP_METHOD.POST, uri, headers, body);
  }
  private static async requestAsync<T = Object>(
      // This param accepts either a class or object
      model: ResponseModel<T>,
      method: HTTP_METHOD,
      uri: string,
      headers: CustomHeaders,
      body?: object): Promise<T> {
      const url = new URL(uri, window.location.origin);
      const request = this.buildRequest(url, method, headers, body);
      const bodyResponse = await fetch(request)
          .then(response => this.validate(response, request.headers))
          .then(validResponse => this.extractBody(validResponse))
          // Class instance or object returned here
          .then(extractedBody => this.buildModel(model, extractedBody))
          .catch((error) => { throw this.handleError(error); });
      return bodyResponse;
  }

  // Method that conditionally creates an instance of the passed in model
  // Or returns the object passed in if no model specified
  private static buildModel<T = Object>(
        Model: ResponseModel<T>,
        params: any,
    ): T {
        if (typeof Model === 'object') return params;
        return new Model(params);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...