Reputation: 464
I have an abstract class in TypeScript that I am inheriting for every feature module in my Angular app. This has worked as long as that class was part of the project. Here is a shortened equivalent to the class (it's called Patchbay).
export abstract class Patchbay<A extends AuthSocket> {
protected readonly sockets = {};
constructor() {
this.sockets = {};
}
protected addSocket = (name: string, socket: Socket) {
this.sockets[name] = socket;
}
auth = (socket?: A) A => {
// do random stuff
}
}
Now I've decided to put it into a node module of its own to be able to use it on several projects. The trouble is that now I can only access the functions (addSocket, auth) from withhin the subclass that inherits from the abstract class Patchbay, if I use 'super.auth()', but not if I use 'this.auth()'. And I cannot access them at all from outside the class.
Here is the tsconfig of the Patchbay module:
{
"compilerOptions": {
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"lib": [
"es2015",
"dom"
],
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": false,
"outDir": "./dist/",
"strict": true,
"sourceMap": true,
"target": "es5"
},
"include": ["./src"],
"exclude": ["node_modules", "**/_tests/**"]
}
And here is the resulting patchbay.d.ts (again stripped down to the essentials):
export declare abstract class Patchbay<A extends AuthSocket> {
protected readonly sockets: {
[key: string]: Socket;
};
protected constructor();
protected addSocket: (name: string, socket: Socket) => void;
auth: (socket?: A | undefined) => A;
}
Now, I kind of assume that I need to declare the module and the class properly for the consuming project to be able to view type Patchbay properly. But where do I do that? The patchbay.d.ts is generated automatically, so I cannot put anything in there. Unfortunately, all tutorials I could find only create extremely minimal modules as examples and so they don't cover that. Also, the TypeScript documentation itself is rather vague on the matter of where to declare namespaces, modules, etc.
Any help or finger pointing to the right direction is highly appreciated.
Upvotes: 0
Views: 944
Reputation: 8360
Let me first boil down your problem to the essence:
class A {
auth = () => { console.log('method a') }
}
class B extends A {
method() {
super.auth();
}
}
new B().method()
So why does it happen?
Because class members do not live on the prototype chain. Each instance of class A
or any class derived from A
has it's own copy of that function. You may have some insight looking at how they're created in desugared code:
var A = /** @class */ (function () {
function A() {
this.auth = function () { console.log('method a'); };
}
return A;
}());
That's why you can still access it by this.auth()
but not by super.auth()
.
The solution is simple. Rewrite it as a class method:
class A {
auth() { console.log('method a') }
}
class B extends A {
method() {
super.auth();
}
}
new B().method()
You may also need to check other code calling rewriten functions. As the this
value may differ depending on how they are called now.
Upvotes: 1