Mixin do abstraktní základní třídy v Typescriptu
Chtěl bych do abstraktní základní třídy vmísit některé metody, abych vytvořil novou abstraktní třídu.
Vezměte si následující příklad:
abstract class Base {
abstract method();
}
interface Feature {
featureMethod();
}
class Implementation extends Base implements Feature {
method() {
}
featureMethod() {
// re-usable code that uses method() call
this.method();
}
}
To funguje dobře, ale cílem je vzít implementace rozhraní Feature a přesunout je do mixinu, aby mohly být znovu použity jinými implementacemi třídy Base.
Dostal jsem se k následujícímu, ale v Typescript 2.4.1 to nekonvertuje
type BaseConstructor<T = Base > = new (...args: any[]) => T;
export function MixFeature<BaseType extends BaseConstructor>(TheBase: BaseType) {
abstract class Mixed extends TheBase implements Feature {
featureMethod() {
// re-usable code that uses method() call
this.method();
}
}
return Mixed;
}
class Implementation extends MixFeature(Base) {
method() {
}
}
Ale TypeScript to neschvaluje a říká:
Error:(59, 41) TS2345:Argument of type 'typeof Base' is not assignable to parameter of type 'BaseConstructor<Base>'.
Cannot assign an abstract constructor type to a non-abstract constructor type.
Je možné to nějak fungovat, nebo je to omezení TypeScriptu, že abstraktní základny nelze rozšiřovat pomocí mixinů?
Odpověď č. 1
V současnosti neexistuje žádný způsob, jak popsat typ konstruktoru abstraktní třídy v TypeScriptu. Problém je sledován na GitHubu v Microsoft/TypeScript#5843. Můžete se tam podívat pro získání nápadů. Jeden návrh je, že můžete potlačit chybu jednoduše tím, že prohlásíte, že Base je BaseConstructor:
// no error
class Implementation extends MixFeature(Base as BaseConstructor) {
method() {
}
}
Teď se váš kód kompiluje. Ale všimněte si, že protože neexistuje způsob, jak specifikovat, že BaseConstructor představuje abstraktní konstruktor, bude vrácená třída interpretována jako konkrétní, ať už to chcete, nebo ne, přestože Mixed je deklarována jako abstract:
// also no error; may be surprising
new (MixFeature(Base as BaseConstructor));
Takže zatím budete muset být opatrní, pokud chcete používat mixiny s abstraktními třídami. Hodně štěstí!
