Ограничения подтипа с обобщениями в машинописи - PullRequest
0 голосов
/ 20 апреля 2020

Имея этот код:

export interface IModel {
  id: string;
}

export interface StatusResponse<
  TModel extends IModel = IModel,
  TResponse = any
> {
  item: TModel;
  response: TResponse;
}

export class Transport<TItem extends IModel = IModel> {
  save(item: TItem): StatusResponse<TItem> {

    const result: StatusResponse<TItem> = {
      item: { // << error
        id: ""
      },
      response: {
        stat: "ok"
      }
    };

    return result;
  }
}

Внутри функции save я получаю эту ошибку:

 Type '{ id: string; }' is not assignable to type 'TItem'.
  '{ id: string; }' is assignable to the constraint of type 'TItem', but 'TItem' could be instantiated with a different subtype of constraint 'IModel'.

Что меня смущает, так это то, что интерфейс StatusResponse имеет те же ограничения и значения по умолчанию для generi c TModel, что и класс Transport для TItem, однако внутри функции save они представлены как несовпадение.

Если я кодирую save метод, подобный этому, проблем нет.


  save(item: TItem): StatusResponse {

    const result: StatusResponse = {
      item: {
        id: ""
      },
      response: {
        stat: "ok"
      }
    };

    return result;
  }


Обратите внимание, что я удалил тип generi c из StatusResponse, поэтому он принимает значения по умолчанию.

Я не являюсь конечно, что здесь происходит.

площадка для машинописи

1 Ответ

0 голосов
/ 20 апреля 2020

Подумайте, что произойдет, если использовать вышеуказанный класс с параметром c, требующим дополнительных свойств. Например:

new Transport<{ id: string, additionalProp: string }>()

Метод сохранения даст результат с отсутствующим additionalProp - вот почему вы получаете ошибку.


Не уверен, имеет ли это смысл в вашем случае , но вы можете распространить оригинальный элемент в ответ на сохранение структуры типа:

export class Transport<TItem extends IModel = IModel> {
  save(item: TItem): StatusResponse<TItem> {

    const result: StatusResponse<TItem> = {
      item: {
        ...item,
        id: ""
      },
      response: {
        stat: "ok"
      }
    };

    return result;
  }
}

Детская площадка

...