-
Notifications
You must be signed in to change notification settings - Fork 362
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
Fix TS4094 Declaration emit Error for mixins #5866
Comments
There are probably 2 ways to fix this error:
Other possible approaches are discussed here - microsoft/TypeScript#17744 (comment) |
Comment from @na9da for his investigation result & possible options: So, I took a closer look at this issue for fixing TS4094 #5866 . The error basically says TS cannot emit type declarations for mixin classes with private or protected members. When compiling with tsc with declaration: true , out of aprox 130 errors, 80 of them are TS4094. This happens to a lot of people, they start off with declaration: false and then when they turn it on, they have this error which is tricky to work around. This thread lists some possible options which I had a look at microsoft/TypeScript#17744 (comment) . I'll summarize what I think are our options (I think we need to use a mix of them). |
I think we probably can have a try the "Declare the return type explicitly" approach (might similar to the option 3 @na9da suggesting ). i.e.: export function test (): new() => Object {
return class {
private privateMember () {
}
};
} |
Sample code for two solutions (option 3 & 4) from @na9da export type Constructor<T> = new (...args: any[]) => T;
class BaseModel {
baseMethod() {
return "baseMethod";
}
}
declare abstract class SimpleMixinTemplate {
abstract baz(): string;
simple(): string;
}
export function SimpleMixin<T extends Constructor<BaseModel>>(
Base: T
): T & Constructor<SimpleMixinTemplate> {
abstract class SimpleMixin extends Base {
abstract baz(): string;
private privateState = "privateState";
private privateMethod() {
return this.privateState;
}
simple() {
return this.privateMethod();
}
}
// Option 3: No casting required here when not using `protected` members. So TS will
// report errors if our SimpleMixin implementation differs from the
// advertised interface in SimpleMixinTemplate.
return SimpleMixin;
}
class TestSimple extends SimpleMixin(BaseModel) {
baz() {
return "baz";
}
}
function testSimple() {
const test = new TestSimple();
console.log(test.simple(), test.baz(), test.baseMethod());
}
declare abstract class ProtectedMixinTemplate {
protected abstract bar(): string;
foo(): string;
}
export function ProtectedMixin<T extends Constructor<BaseModel>>(
Base: T
): T & Constructor<ProtectedMixinTemplate> {
abstract class ProtectedMixin extends Base {
protected abstract bar(): string;
foo() {
return this.bar();
}
}
// Option 4: We need to force the cast. So TS won't throw any errors if the mixin implementation
// deviates from the advertised interface in ProtectedMixinTemplate.
return ProtectedMixin as unknown as T & Constructor<ProtectedMixinTemplate>;
}
class TestProtected extends ProtectedMixin(BaseModel) {
bar() {
return "bar";
}
}
function testProtected() {
const test = new TestProtected();
console.log(test.foo(), test.baseMethod());
}
function test() {
testSimple();
testProtected();
}
test(); |
had a chat with @na9da so to make it clear:
|
Here is a playground example of option 4: Playground Link |
There is also a symbol-based property hiding solution I think might help with an easier solution under certain circumstances : |
@na9da created a new branch that adopted a different approach to solve this:
|
See:
Out of 133 type errors we need to solve,
exported anonymous classes can't have private or protected members, because there's no way to represent that in a .d.ts file.
This ticket is about solving the errors (from the google docs link below) that are related to issue above.
https://docs.google.com/spreadsheets/d/12lDW0jfA-2x6A4LE9J9BSXXaWNpClk1Ypm4_E8kB0bo
The text was updated successfully, but these errors were encountered: