ANGULAR: Как расширить абстрактный класс на два уровня с помощью дженериков - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь расширить класс двумя уровнями наследования с помощью шаблонов, как на следующей диаграмме:

enter image description here

Первая попытка, я объявил BaseResourceTableComponent как расширение BaseResourceListComponent<T extends BaseResourceModel>:

export abstract class BaseResourceModel {
    public id?: number;
}

export abstract class BaseResourceListComponent<T extends BaseResourceModel> {
  public resources: T[] = [];
  ...
}

export abstract class BaseResourceTableComponent extends BaseResourceListComponent<T extends BaseResourceModel>  { // <--- ERROR!
  dataSource: MatTableDataSource<T>;
  ...
}

// now, the non abstract classes

export class User extends BaseResourceModel {
  constructor(
    public name?: string,
  ) {
    super();
  }

export class UserTableComponent extends BaseResourceTableComponent<User> {
  ...
}

Я получаю следующую ошибку:

ошибка TS2304: не удается найти имя 'T'.

Вторая попытка, я объявил BaseResourceTableComponent как расширение BaseResourceListComponent<BaseResourceModel> (без T extents):

export abstract class BaseResourceModel {
    public id?: number;
}

export abstract class BaseResourceListComponent<T extends BaseResourceModel> {
  public resources: T[] = [];
  ...
}

export abstract class BaseResourceTableComponent extends BaseResourceListComponent<BaseResourceModel>  {
  dataSource: MatTableDataSource<BaseResourceModel>;
  ...
}

// now, the non abstract classes

export class User extends BaseResourceModel {
  constructor(
    public name?: string,
  ) {
    super();
  }

export class UserTableComponent extends BaseResourceTableComponent<User> { // <--- ERROR!
  ...
}

Проходит, ошибки в объявлении BaseResourceTableComponent нет, но я далее получите следующую ошибку при объявлении UserTableComponent:

ошибка TS2315: Тип 'BaseResourceTableComponent' не является универсальным c.

I я действительно запутался здесь!

Я что-то упустил? Обходные

Ответы [ 2 ]

1 голос
/ 28 февраля 2020
export abstract class BaseResourceListComponent<T extends BaseResourceModel> {
  public resources: T[] = [];
  ...
}

Здесь вы определяете класс BaseResourceListComponent с помощью обобщенного c типа T extends BaseResourceModel. Часть extends BaseResourceModel - это ограничение типа , которое накладывает ограничения на типы, которые может иметь T. Это означает, что T должен быть либо BaseResourceModel, либо одним из его подтипов .
Тип B является подтипом из A, если B имеет тип A и содержит дополнительную информацию (например: свойства , методы ).

export abstract class BaseResourceTableComponent extends BaseResourceListComponent<T extends BaseResourceModel>  { // <--- ERROR!
  dataSource: MatTableDataSource<T>;
  ...
}

Здесь вы получите ошибку, поскольку BaseResourceListComponent ожидает тип, и здесь вы предоставляете T extends BaseResourceModel, но вы вообще не определили T.

Вы можете решить это с помощью

export abstract class BaseResourceTableComponent<T extends BaseResourceModel> extends BaseResourceListComponent<T> { }

Теперь T является тип, независимо от того, является ли он конкретным или универсальным c, если T удовлетворяет ограничению: extends BaseResourceModel.

TypeScript Playground

0 голосов
/ 28 февраля 2020

Обе ваши проблемы вызваны тем, что BaseResourceTableComponent не был объявлен generi c.

export abstract class BaseResourceTableComponent extends BaseResourceListComponent<T extends BaseResourceModel> говорит, что параметр generic c для BaseResourceListComponent равен T, но не дает в любом случае, чтобы определить, что такое T, потому что BaseResourceTableComponent не задает конкретный параметр и не дает способа объявить параметр generi c, который может быть по существу передан родительскому классу.

Расширение generi c класс не делает класс, делающий расширяющийся универсальный; На самом деле, вы пытаетесь полагаться именно на это с export class UserTableComponent extends BaseResourceTableComponent<User>.

...