-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using mixins throws TS4093, TS4020 and TS4060 when exporting the class that extends the result of a mixin #15066
Comments
This is still a bit painful. I was talking to @alexeagle and others about this today. You can get around this by creating an explicit interface for your inner export class FooItem {
name?: string;
toString(): string {
return ""
}
}
// Instance side:
export interface WithTagsInstance {
tags(): Promise<any>
}
// Constructor static side:
export interface WithTagsStatic {
getTags(): Promise<any>;
new (...args: any[]): WithTagsInstance;
}
export function WithTags<T extends Constructor<FooItem>>(Base: T): WithTagsStatic & T {
return class extends Base {
static getTags(): Promise<any> { throw 1; }
tags(): Promise<any> { throw 1; }
}
} Then later on, you unfortunately cannot immediately extend export const FooItemWithTags = WithTags(FooItem)
export class Test extends FooItemWithTags {} So that there's a direct name that TypeScript can reference. |
I see. Though, if my
Furthermore, It also complains about the export class Test extends WithTags(FooItem) {
// Error TS2425: Class 'WithTagsInstance & FooItem' defines instance member property 'toString', but extended class 'Test' defines it as instance member function.
toString(): string {
return '';
}
} I'm also curious how would I implement the mixin if export abstract class Item {
foo(): void {}
}
export abstract class FooItem extends Item {
name?: string;
toString(): string {
if (this.name) {
return this.name;
}
return `${this.id}`;
}
}
...
// This definitely doesn't work ...
export const FooItemWithTags = WithTags(FooItem)
export class Test extends FooItemWithTags {} |
It seems TS either need to natively support mixin or support function call signature, #6606. Otherwise it is quite hard to generate optimal declaration file. |
This should be covered by #14075, but leaving it open to ensure we capture all the scenarios. |
How to deal with protected members in Mixins then? |
A simple fix is up at #15932. It just emits class expressions as type literals, but it's enough to make this scenario work. |
Thanks very much. I used it with typescript version 2.6.1. It works like a charm. Even allows to extend later the mixed classes. That's how i used it in my project: see the MixedBaseObject function there https://github.com/BBGONE/JRIApp/blob/master2/FRAMEWORK/CLIENT/shared/jriapp_shared/utils/mixobj.ts |
Yes, it works, but the problem that i need to have a constructor. This mixing works only on classes. EcmaScript6 now has a Proxy object, which can be used to add properties, methods to a given object, thus adding members to the interface. I can not use this mixing function in this case. Types union does not work either, because T | U type is not the same as T extends U. |
I've found that typescript has intersection types Type1 & Type2. I did not noticed it before. It is perfect for mixing. |
TypeScript Version: 2.2.1
Code
I'm having some problems with using the new syntax for mixins. Consider the following example:
Expected behavior:
It should not throw any errors.
Actual behavior:
It throws those three errors that are described in the code comments.
The text was updated successfully, but these errors were encountered: