TypeScript: возможно ли реализовать свойство абстрактного класса свойством, унаследованным от типа, указанного в абстрактном? - PullRequest
0 голосов
/ 12 апреля 2019

Абстрактный класс ParentClass в приведенном ниже коде должен работать с абстрактным свойством significantEntity (которое является экземпляром класса, унаследованным от абстрактного SignificantEntityParent). Конечно, приведенный ниже код недопустим, потому что significantEntity реализации имеют тип, отличный от SignificantEntityParent.

abstract class SignificantEntityParent {}
class SignificantEntity1 extends SignificantEntityParent {}
class SignificantEntity2 extends SignificantEntityParent {}

abstract class ParentClass {

  protected abstract significantEntity: SignificantEntityParent;

  public testMethod(): void {
    console.log(this.significantEntity);
  }
}

class TestClass1 extends ParentClass {
  constructor() {
    super();
    // invalid!
    this.significantEntity = new SignificantEntity1();
  }
}

class TestClass2 extends ParentClass {
  constructor() {
    super();
    // invalid!
    this.significantEntity = new SignificantEntity2();
  }
}

Я попробовал обход с абстрактным универсальным методом getSignificantEntity<SignificantEntity extends SignificantEntityParent>(): SignificantEntity.

abstract class ParentClassA {

  protected abstract getSignificantEntity<SignificantEntity extends SignificantEntityParent>(): SignificantEntity;

  public logSignificantEntity(): void {
    console.log(this.getSignificantEntity());
  }
}

class TestClassA1 extends ParentClassA {

  private significantEntity: SignificantEntity1;

  constructor() {
    super();
    this.significantEntity = new SignificantEntity1();
  }

  protected getSignificantEntity(): SignificantEntity1 {
     return this.significantEntity;
  }
}

class TestClassA2 extends ParentClassA {

  private significantEntity: SignificantEntity2;

  constructor() {
    super();
    this.significantEntity = new SignificantEntity2();
  }

  protected getSignificantEntity(): SignificantEntity2 {
    return this.significantEntity;
  }
}

Я получаю много ошибок:

  • TS2416: Свойство 'getSignificantEntity' в типе 'TestClassA' нельзя назначить одному и тому же свойству в базовом типе 'ParentClassA'.
  • Тип '() => SignifcantEntity1' нельзя назначить типу 'SignificantEntity extends SignificantEntityParent> () => SignificantEntity'.
  • Тип «SignificantEntity1» нельзя назначить типу «Существенная сущность».

Не могу понять, что TypeScript пытается мне сказать. Есть ли правильный подход для работы с significantEntity внутри абстрактного класса?

1 Ответ

2 голосов
/ 12 апреля 2019

Это не может быть четко задокументировано, но абстрактные свойства и методы абстрактных классов должны быть объявлены в конкретных подклассах;они не могут быть просто использованы .Это означает, что вы можете исправить свой первый пример, добавив конкретные объявления свойств:

class TestClass1 extends ParentClass {
    significantEntity: SignificantEntity1; // declaration   
    constructor() {
        super();
        this.significantEntity = new SignificantEntity1();
    }
}

class TestClass2 extends ParentClass {
    significantEntity: SignificantEntity2; // declaration
    constructor() {
        super();
        this.significantEntity = new SignificantEntity2();
    }
}

Конечно, если все, что вы делаете в конструкторе, это инициализация свойства, вы можете удалить конструктор и использовать явный инициализатор свойства , который служит как объявлением, так и инициализацией:

class TestClass1 extends ParentClass {
    significantEntity = new SignificantEntity1();
}

class TestClass2 extends ParentClass {
    significantEntity= new SignificantEntity2();
}

Хорошо, надеюсь, это поможет.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...