Typescript call function from base class - javascript

is there a way to call a function from baseclass like overwrite.
Base Class
export class BaseClass {
constructor() {
//do something asynchronous
//than call initialized
}
}
Inheritance Class
export class InheritanceClass extends BaseClass {
initialized() {
// get called from base class
}
}

Do you mean like this:
class Base {
constructor(){
setTimeout(()=>{
this.initialized();
}, 1000);
}
initialized(){
console.log("Base initialized");
}
}
class Derived extends Base {
initialized(){
console.log("Derived initialized");
}
}
var test:Derived = new Derived(); // console logs "Derived initialized" - as expected.
Works well in the Playground (Ignore the odd red underline on setTimeout(), which I think is a bug - it compiles and runs fine.)
You do need the method present on Base, but you can override it in Derived (with or, as in this case, without a call to super.initialized()).

In order to do that you would need to have initialized as an abstract member of the abstract class. typescript currently does not support this however the feature has been asked for and there is a work item open for it:
http://typescript.codeplex.com/workitem/395

Related

Inaccessible method on TS object

I am attempting to make use of a method that is stored on a Typescript class from within a Vue component.
When attempting to use a method defined on said class from another class (which just so happens to be a Typescript Vue component), an Uncaught TypeError is returned to the console saying that the method I am trying to make use of is not a function
Consider the following Paper class:
export class Paper {
paperSize: number;
documentTitle: string;
constructor() {
paperSize = 1;
documentTitle = "Arbitrary title";
}
getDocumentRatio(): number {
return ArbitraryLibrary.arbitraryNumericFunction(this.paperSize);
}
}
When trying to use this class (the Vue component) in another class like:
#Component()
export class PaperUser {
paper = new Paper();
paperUserMethod() {
...
const unimportant = this.paper.getDocumentRatio();
...
}
...
// Wherever the method gets used
this.paperUserMethod();
...
}
Execution of the method is then interrupted, because using the function in this manner creates the TypeError
Initially thinking that this might be a binding issue I attempted something more like
...
this.paper.getDocumentRatio().bind(this.paper);
...
but evidently this does not work because binding in this way would be as effective as method chaining - with the IDE (VSCode) asserting that property 'bind' does not exist on type 'number'.
On first hand, you have to set your attribut in your constructor with this.myAttribut and on second hand you are using your method out of a method implementation of you class, you can try this :
class Paper {
paperSize: number;
documentTitle: string;
constructor() {
this.paperSize = 1;
this.documentTitle = "Arbitrary title";
}
getDocumentRatio(): number {
// try to be trivial on first attempt
return this.paperSize;
}
}
class PaperUser {
paper = new Paper();
paperUserMethod() {
return this.paper.getDocumentRatio();
}
usePaperuser(){
this.paperUserMethod();
}
}

Getting the name of a class on which a static function has been called

So my question is as follows: Can I get the name of a class on which a function got called? To illustrate that problem I will give a short code example.
class Base {
static getClassName() {
// get the caller class here
}
}
class Extended extends Base { }
Base.getClassName(); // Base
Extended.getClassName(); // Extended
Can anyone tell me how to do this, or say if this is even possible.
The following code should work:
class Base {
static getClassName() {
return this.name;
}
}
class Extended extends Base {}
console.log(Base.getClassName()); // Base
console.log(Extended.getClassName()); // Extended
In a static method, this refers to the class object itself.
In ES6, functions have a read-only name field (doc). Since classes are functions, you can simply use MyClass.name to statically get the class name.
To get the class name of functions at runtime, reference the Function.name of the constructor function.
class Base {
getClassName() {
return this.constructor.name;
}
}
class Extended extends Base {}
console.log(Base.name);
console.log(Extended.name);
const base = new Base();
console.log(base.getClassName());
const extended = new Extended();
console.log(extended.getClassName());

Typescript decorate class add new method

I want to add a new method to a decorated class. Everything works well but the compiler complains that the method does not exist, how can I satisfy the compiler?
export function decorate( constructor : Function ) {
constructor.prototype.someMethod = function () {
}
}
#decorate
class Test {
constructor() {
//Property 'someMethod' does not exist on type 'Test'.
this.someMethod();
}
}
You could use:
(<any>this).someMethod();
or:
this['someMethod']();
You can't use interfaces to check that this contains method someMethod() because you're not in fact implementing the interface so I think these two are the only options...

extend non ES6 object

Working to understand the new ES6 syntax. If I have a class like the Outlayer library that is not written in ES6 but want to extend it with an ES6 class how would that look? The key extension point is _getItemLayoutPosition
I tried something like this.
export let MyGrid = Outlayer.create('AnyGrid', {});
MyGrid._getItemLayoutPosition = function() {
// this does not get called
}
If I do new MyGrid(element)
My extended _getItemLayoutPosition never gets called.
So then I thought maybe I need to extend the class
export class AnyGrid extends Outlayer {
_getItemLayoutPosition(item) {
return {
x: 0,
y: 0
}
}
}
This gives an error Type 'typeof 'Outlayer'' is not a constructor function type.
What is the proper way to extend this class so that I can override the _getItemLayoutPosition method?
Since Outlayer.create actually creates a function that inherits from Outlayer you have to add the method on the prototype instead of the function itself
export let MyGrid = Outlayer.create('AnyGrid', {});
MyGrid.prototype._getItemLayoutPosition = function() {
// this does not get called
}
Note that the function returned when you call Outlayer.create has additional properties i.e. is not the same as creating a class that inherits from Outlayer
Please try the following:
// AnyGrid- subclass
function AnyGrid() {
Outlayer.apply(this, arguments); // call super constructor.
}
// subclass extends superclass
AnyGrid.prototype = Object.create(Outlayer.prototype);
AnyGrid.prototype.constructor = AnyGrid;
//Add/Override the method
AnyGrid.prototype._getItemLayoutPosition = function() {
// this does not get called
}
Don't forget to export AnyGrid.

Typescript: Type inference when using decorator

I wonder why when I use decorators or annotations in Typescript on a class. The compiler can't infer the new type of the class. If I don't use decorators and use the old way to do this in ES5 (ie. call manually the decorator) it obviously works.
For instance, here a sample that shows the issue:
function decorate(Target: typeof Base): IExtendedBaseConstructor {
return class extends Target implements IExtendedBase {
public extendedtMethod(): number {
return 3;
}
};
}
interface IBase {
baseMethod(): number;
}
interface IExtendedBase extends Base {
extendedtMethod(): number;
}
interface IExtendedBaseConstructor {
new(): IExtendedBase;
}
#decorate
class Base implements IBase {
public baseMethod(): number {
return 5;
}
}
const test = new Base();
test.baseMethod(); // OK
test.extendedtMethod(); // NOT OK, typescript think, Base is still Base but we decorated it.
With the older way, it works:
class Base implements IBase {
public baseMethod(): number {
return 5;
}
}
const ExtendedBase = decorate(Base);
const test = new ExtendedBase();
test.baseMethod(); // OK
test.extendedtMethod(); // OK
Thanks in advance.
Right now this doesn't work. There is a pending issue on github to allow class decorators to change the type of the class.
I would recommend doing the "old way" you mentioned until this is implemented.
There is a way to make this work with just a little extra coding required.
For any class decorator, create an interface with its properties and methods. Name it in a way so you can easily associate it with the decorator it's describing. In your case, it could be:
interface IDecorate {
extendedtMethod(): number;
}
For any class that needs this decorator, you simply create an interface with the same name as the class and let it extend all necessary decorator interfaces:
#decorate
#anotherDecorator
class MyClass {
// ...
}
interface MyClass extends IDecorate, IAnotherDecorator {}
Now, just turn off ESLint's or TSLint's warnings for empty interfaces and you should be ready to go. Any method or property added by the decorator will now be available to use within the decorated class itself.

Categories

Resources