javascripttypescripttypescript-typingstypescript2.0

this keyword in class method as a function parameter in typescript


Tried to pass this with type in a class method and then try to access it in 2 ways:

  1. Create a new JS object and assign a value. (No Error)

    {getName: obj1.getName} in below code

  2. Save it to a new variable(reference) and call it (Gives Error)

    const a = obj1.getName; in below code

What is the concept behind these two? When I have defined this: MyClass saying it is of type MyClass then it should give error for the first one as well.

typescript code

class MyClass {
    x:string = "Class value";
    
    getName(this: MyClass) {
        return this.x;
    }
}

// Creating class object
const obj1 = new MyClass();
console.log(obj1.getName());

// Creating JS object
const obj2 = {x: 'Object Value', getName: obj1.getName}

// Will not give error
console.log(obj2.getName());

// Will give error with below line
const a = obj1.getName;
a(); 

Error: The 'this' context of type 'void' is not assignable to method's 'this' of type 'MyClass'.(2684)

Ref:


Solution

  • In the above code obj2 has same signature/definition as MyClass thats why it consider that object as an instance of class MyClass and hence didn't give error.

    While in second case it has different signature and hence typescript gave error.

    If we try to create obj2 with x as a number, then signature gets different and it will give error:

    Example:

    const obj2 = {x: 123, getName: obj1.getName}
    

    Error: The 'this' context of type '{ x: number; getName: (this: MyClass) => string; }' is not assignable to method's 'this' of type 'MyClass'

    Another example:

    class MyClass {
        x:string = "Class value";
        
        getName(this: MyClass) {
            // Now returning a string directly removing reference.
            return 'Hello';
        }
    }
    const obj1 = new MyClass();
    console.log(obj1.getName());
    
    // Creating JS object
    const obj2 = {x: 3, getName: obj1.getName}
    
    // Will now give error
    console.log(obj2.getName());
    

    Error:

    The 'this' context of type '{ x: number; getName: (this: MyClass) => string; }' is not assignable to method's 'this' of type 'MyClass'.
      Types of property 'x' are incompatible.
        Type 'number' is not assignable to type 'string'.(2684)