0

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:

Rajat Jain
  • 1,339
  • 2
  • 16
  • 29
  • "*What is the concept behind these two?*" [How does the "this" keyword work, and when should it be used?](https://stackoverflow.com/q/3127429) and [How to access the correct `this` inside a callback](https://stackoverflow.com/q/20279484) – VLAZ May 30 '23 at 06:23
  • I need the answer for "When I have defined this: MyClass saying it is of type MyClass then it should give error for the first one as well." – Rajat Jain May 30 '23 at 06:43
  • TS doesn't have exact types. It has structural equality. `obj` is structurally compatible with `MyClass`, therefore the type fits. [What is structural typing?](https://github.com/Microsoft/TypeScript/wiki/FAQ#what-is-structural-typing) – VLAZ May 30 '23 at 06:46
  • Yes this is right. I have found the root cause. Please find the answer below. Appreciate your time in following up. Thank you. :) – Rajat Jain May 30 '23 at 06:50

1 Answers1

1

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)
Rajat Jain
  • 1,339
  • 2
  • 16
  • 29