Dealing with the "this" problem in TypeScript and its impact on scope

Here is my code snippet:

class MyClass {
    name = "MyClass";

    // traditional method definition
    getName1(){
        return this.name;
    }

    // method defined as an arrow function
    getName2 = () => {
        return this.name;
    }

    // traditional method definition using a this parameter
    getName3(this: MyClass){
        return this.name;
    }
}

const c = new MyClass();
const obj = {
    name: "obj",
    getName1: c.getName1,
    getName2: c.getName2,
    getName3: c.getName3
};

const g = c.getName3;

console.log(c.getName1());
// "MyClass" because this is called in the context of c
// using a traditional method definition getName1

console.log(c.getName2());
// "MyClass" because this is called in the context of c
// using an arrow function getName2

console.log(c.getName3());
// "MyClass" because this is called in the context of c
// using a traditional method definition getName3, having
// a this parameter that statically enforce the context of c

console.log(obj.getName1()); 
// "obj" because this is called in the context of obj
// using the MyClass traditional method definition getName1()
// and assigning it to obj's getName1 property

console.log(obj.getName2()); 
// "MyClass" because this is called in the context of obj
// using an arrow function getName2 and assigning it 
// to obj's getName2 property, but which will preserve c's context
// nonetheless

console.log(obj.getName3()); 
// "obj" but why? Isn't the context of this enforced as that of MyClass? Shouldn't I get
// « The 'this' context of type 'obj' is not assignable to method's 'this' of type 'MyClass' »

console.log(g()); 
// Error, the 'this' context of type 'void' is not assignable to method's 'this' of type 'MyClass'.
// but isn't g declared in the global this context?

I have some questions regarding the functionality. They are outlined in the comments, but here they are summarized:

  1. Why does console.log(obj.getName3()); show "obj"? Shouldn't the context of this be restricted to that of MyClass, resulting in an error message like:

The 'this' context of type 'obj' is not assignable to method's 'this' of type 'MyClass'

  1. I know that g is not declared within an object or class context. However, since it is defined at the global level, shouldn't this refer to globalThis? If so, then why am I seeing the following error:

The 'this' context of type 'void' is not assignable to method's 'this' of type 'MyClass'.

Answer №1

It seems like TypeScript automatically identifies the "outer" object as 'this', hence retrieving "obj" from obj.getName3(), which is acceptable because it aligns with the class structure. This object contains the necessary attributes and methods, making it a valid match.

However, if you were to modify obj.name to obj.noname (or any of the function names), calling obj.getName3() would no longer be possible since the object would no longer correspond to the class.

The same principle applies to g(). The outer object in this case is void and lacks a name attribute (along with the functions), resulting in a different error message being displayed.

To delve deeper into this topic, check out: https://www.typescriptlang.org/docs/handbook/2/functions.html#declaring-this-in-a-function

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to extract a specific item from a ListView by tapping on it in Nativescript?

Attempting to retrieve data from a tap event using angular2 + typescript: This is the html code for the component: <RadListView row="1" [items]="groceryList" [class.visible]="listLoaded" (tap)="seeItem($event)" swipeActions="true" (itemSwipeProgr ...

When using react-admin with TypeScript, it is not possible to treat a namespace as a type

Encountering issues while adding files from the react-admin example demo, facing some errors: 'Cannot use namespace 'FilterProps' as a type.' Snippet of code: https://github.com/marmelab/react-admin/blob/master/examples/demo/src/orde ...

I'm having trouble retrieving the value from the textbox in my Angular 7 project using TypeScript

I'm currently working with Angular 7 and trying to create a textbox to display its value in an alert. However, I'm facing difficulty in fetching the textbox value in typescript. I would appreciate any guidance on how to proceed with this issue. ...

Unable to access variables beyond the function scope results in an undefined value

I'm currently working with an npm package that shortens URLs but I'm struggling because there isn't much documentation available. The package takes the "this.src" URL and shortens it, but when I try to use the "url" element in HTML, it retur ...

There was a problem with the module '@angular/material' as it was unable to export a certain member

In creating a custom Angular Material module, I have created a material.module.ts file and imported various Angular Material UI components as shown below: import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/commo ...

The TypeScript alternative to Axios request with native fetch functionality

I have a function that sends a JWT validation request: const sendValidateJWTRequestFetch = (url: string, token: string) => fetch(url, { method: 'GET', mode: 'cors', headers: { Authorization: token, 'Ac ...

Step-by-step guide for resolving the issue of "Observable.share is not recognized as a function" in Angular 2

When working with cache structure in Ionic 2, I often encounter an error when defining an observable array to store data retrieved from the server. How can I troubleshoot this issue and resolve it? marketArray : Observable<any>; /* GLOBAL */ th ...

Ensuring the proper typescript type for assigning a value in react-hook-form

I'm encountering an issue when trying to pass the function setValue() down to a child component. The error message I receive is: Type 'UseFormSetValue<Inputs>' is not assignable to type 'UseFormSetValue<Record<string, any> ...

Specifying the return type of a function as a combination of the types of the input arguments

Is there a way to safely implement the given function in TypeScript without using unsafe casts or an extensive number of function overloads with various input permutations? interface Wrapped<T> { type: string; data: T; } interface WrappedA&l ...

Add a feature to a functional component that is enclosed with React.forwardRef

Within my codebase, there exists a component that is wrapped with React.forwardRef and serves as a compound component. One challenge I encountered was how to preserve the functionality of Form.Item = FormItem; while still having the Form component fun ...

Can Material UI be defined as a peerDependency while maintaining its types as a DevDependency?

Is there a way to set Material UI as a peerDependency while keeping its types as DevDependency? I'm currently working on a component library using React + Typescript, with components based on Material UI and Rollup as the module bundler. For example ...

Encountering an Uncaught TypeError when attempting to set properties of null with useRef

I've been working on an app that requires access to the user's device camera in order to display live video on the screen. I've managed to achieve this by utilizing a video HTML Object and setting the media stream as its srcObject. Everythin ...

Creating a mongoDB query that matches elements in an array of subdocuments with elements in a Typescript Array

In my database, I have stored various Events using mongoDB. Each event comes with multiple fields, including an array of genres, which consists of subdocuments like {genre and subGenre}. For instance, an event could be classified as {genre: "music", subGe ...

Angular 14: A collection and schematic must be provided for execution to proceed with the process

I've recently started learning angular. After installing the latest version, I created an app called "test" using the command ng new test. Next, I opened the app in Visual Studio Code and tried to create a new component by entering the command: ng g ...

The alignment of the first and second steps in Intro.js and Intro.js-react is off

There seems to be an issue here. Upon reloading, the initial step and pop-up appear in the upper left corner instead of the center, which is not what I anticipated based on the Intro.js official documentation. https://i.stack.imgur.com/ICiGt.png Further ...

Discovering the type in Typescript without explicitly defining a type variable for the callback

I am looking for a solution to wrap rxjs subscribe's next callback with my own function: type Handler<T> = (value: T) => void; export function withTryCatch<T>(callback?: Handler<T>): Handler<T> { return (value: T) => ...

Utilizing JavaScript variables imported from an external library in Next.js: A Guide

I am currently working on a Next.js with Typescript website and I am in the process of adding advertisements. The ad provider has given me instructions to embed this JavaScript code on my site: <script src="//m.servedby-buysellads.com/monetization. ...

When running the test, a "is not defined" ReferenceError occurs in the declared namespace (.d.ts) in ts-jest

When running typescript with ts-jest, the application functions properly in the browser but encounters a ReferenceError: R is not defined error during testing. The directory structure: |--app | |--job.ts |--api | |--R.d.ts |--tests | |--job.test.ts ...

Importing Json in Angular 8: A detailed guide

I recently came across information that you can now directly import JSON in TypeScript 2.9 and made changes to my tsconfig.json file accordingly: { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", " ...

Having trouble incorporating @types/pdfmake into an Angular project

I have been experimenting with integrating a JS library called pdfmake into an Angular application. I found some guidance on how to accomplish this at https://www.freecodecamp.org/news/how-to-use-javascript-libraries-in-angular-2-apps/, which involved usin ...