-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
TypeScript Version: typescript@2.9.0-dev.20180323
Search Terms:
mixin extends mixin
mixin conflicting declarations
mixin base contraint
Summary
I want to write two mixin classes, Foo
and Bar
. Bar
requires access to the protected interface of Foo
. Therefore I use TS2.8 conditional types to extract the type of a Foo
class and use this type as a generic constraint for the Bar
mixin's Base
class.
Unfortunately, this causes mysteriously inconsistent "conflicting declaration" errors. The inconsistency suggests this is a bug instead of an intended type warning.
Code
class BaseClass {/* ... */}
/* Type error highlighted on "Composed" */
class Composed extends BarMixin(FooMixin(BaseClass)) {}
type Constructor<I = {}> = new (...args: any[]) => I;
interface EmptyInterface {}
/** Mixin */
function FooMixin<C extends Constructor>(Base: C) {
return class extends Base {
private _referenceToEmptyInterface: EmptyInterface = {}; // Causes the error. Why?
private _fooPrivate: number = 0; // Does not cause an error. Why not, given the above?
protected _fooProtected: number = 0;
}
}
/** Type of class that creates instances of type Foo */
type FooConstructor = typeof FooMixin extends (a: Constructor) => infer Cls ? Cls : never;
/** Mixin that can only extend subclasses of Foo */
function BarMixin<C extends FooConstructor>(Base: C) {
return class extends Base {
barMethod() {
// We require `Base` to implement `Foo` because we need access to protected `Foo` properties.
this._fooProtected++;
}
}
}
Expected behavior:
No errors.
Actual behavior:
index.ts(4,7): error TS2415: Class 'Composed' incorrectly extends base class 'BarMixin<{ new (...args: any[]): FooMixin<typeof BaseClass>.(Anonymous class); prototype: FooMixi...'.
Type 'Composed' is not assignable to type 'BarMixin<{ new (...args: any[]): FooMixin<typeof BaseClass>.(Anonymous class); prototype: FooMixi...'.
Property '_referenceToEmptyInterface' has conflicting declarations and is inaccessible in type 'Composed'.
Playground Link (will not work until the playground is updated to TS2.8)
Related Issues:
I asked on StackOverflow: https://stackoverflow.com/questions/49458031/