Reference same class

Viewed 263
class MyClass{

  someMethod(): MyClass{
     return new MyClass();
  }

}

How to reference current class, without explicitly passing the name?

Something like this:

class MyClass{

  someMethod(): self{
     return new self();
  }

}

Obviously that doesn't work, but you get the idea.

6 Answers

TypeScript will not recognize this.constructor as callable. Use Object.getPrototypeOf(this).constructor to get a reference to it instead.

This is the most straightforward way of doing this with strict type safety:

class SelfReference {
    /**
     * Assign some constructor arguments to the instance for testing.
     */
    constructor(private a: number, private b: number) {}

    /**
     * Create a new instance of `Object.prototypeOf(this).constructor`.
     */
    newInstance(...args: ConstructorParameters<typeof SelfReference>) {
        const { constructor } = Object.getPrototypeOf(this);
        return new constructor(...args);
    }
}

const firstReference = new SelfReference(1, 2);
const newReference = firstReference.newInstance(3, 4);

console.log({ firstReference, newReference });

Logs:

[LOG]: {
  "firstReference": {
    "a": 1,
    "b": 2
  },
  "newReference": {
    "a": 3,
    "b": 4
  }
} 

I would not recommend doing this though, it's a pretty ugly anti-pattern.

TypeScript Playground

This can be accomplished by using getPrototypeOf:

Class myclass {

  constructor() {}
  class(): this {
    const ctor = Object.getPrototypeOf(this).constructor;
    return new ctor();
  }
}

Using the ctor(), we are not calling myclass specifically!

Mozilla - Globa_Objects/Object/getPrototypeOf

class MyClass {

    returnClass(): MyClass {
        return new (this.constructor as typeof MyClass)();
    }
}

const x: MyClass = new MyClass();
const newClass: MyClass = x.returnClass();

this is what you want !

class Foo {
    foo(): this {
        return this;
    }
}

class Bar extends Foo { }


const bar: Bar = new Bar().foo();

Playground

Does this do what you want? You can explicitly grab the current constructor to make a "new this".

class MyClass{

  someMethod(){
     return new this.constructor();
  }
}

let x = new MyClass();
let y = x.someMethod();

Here is a TypeScript solution.

There doesn't seem to be a way to use the this keyword in the function signature of a static method or the this.constructor keyword in the function signature of an instance method, both which would be equivalent to the Self keyword in other languages. However, as the this/this.constructor keyword would represent an instance of the Foo class, and an instance of a class which extends from the Foo class can be returned from a function with return type Foo, the return type of the function doesn't have to be a special keyword, but can just be the class name.

class Foo {
  static createNewClass(): Foo {
    return new this();
  }
  
  name = "Foo";
  
  createNewClass(): Foo {
    return new (this.constructor as typeof Foo)();
  }
}

class Bar extends Foo {
  name = "Bar";
}

const foo = new Foo();
const fooFromStaticMethod = Foo.createNewClass();
const fooFromMethod = foo.createNewClass();

const bar = new Bar();
const barFromStaticMethod = Bar.createNewClass();
const barFromMethod = bar.createNewClass();

console.log(fooFromStaticMethod.name, fooFromMethod.name, barFromStaticMethod.name, barFromMethod.name);

Playground

Related