TypeScript: Unidentified reference to 'this' within the class

typescript version: 3.9.2

The goal is to define an interface constraint that permits only non-functional member keys on the class

type NonFunctionKeys<T extends {}> = {
  [K in keyof T]-?: T[K] extends Function ? never : K
}[keyof T];

class MyClass {
  someKey: boolean = true;
  set<T extends keyof this>(key:T, value: this[T]) {
  }
  setValue<T extends NonFunctionKeys<this>>(key:T, value: this[T]) {
  }
  foo() {
    // valid
    this.set('someKey', true);
    // valid
    (this as MyClass).setValue('someKey', true);
    // next line will show error
    // 2345: Argument of type '"childValue"' is not assignable to parameter of type 'this[keyof this] extends Function ? never : keyof this'.
    this.setValue('someKey', true);
  }
}

// all good 
const c = new MyClass();
c.set('someKey', true)
c.setValue('someKey', true)

Does typescript not acknowledge this? However, IDE provides correct hints, and type inference is accurate when using attributes

PS: additional note, while the scenario here may seem simple, it actually involves inheritance - the value of the set could be a property of the super class, or in case of inheritance, the subclass might have additional properties, hence why I can't specify MyClass instead of this

Answer №1

It seems like achieving what you're suggesting is quite challenging. When you need to call the setValue function from a point where the object's class hierarchy is unknown until runtime, even the type system won't be able to predict it. Therefore, the best approach would be to handle all possible scenarios by manually checking and casting at runtime, as demonstrated below:

type NonFunctionKeys<T extends {}> = {
    [K in keyof T]-?: T[K] extends Function ? never : K
}[keyof T];

class MyClass {
    someKey: boolean = true;
    set<T extends keyof this>(key: T, value: this[T]) {
    }
    setValue<T extends NonFunctionKeys<this>>(key: T, value: this[T]) {
    }
    foo() {
        // This works fine
        this.set('someKey', true);
        // This also works fine
        (this as MyClass).setValue('someKey', true);
        // The next line will show an error
         if (this instanceof MyDerivedClass) {
            (this as MyDerivedClass).setValue('otherKey', true);
        } else  if (this instanceof MyClass) {
            (this as MyClass).setValue('someKey', true);
        }
    }
}

class MyDerivedClass extends MyClass {
    otherKey: boolean = false;
}

// This is perfectly valid 
const c = new MyDerivedClass();
c.foo()

I'm not entirely sure why manual casts are required since I would expect type guards to come into play. Nonetheless, performing a manual cast isn't too bothersome considering you've already confirmed that the object belongs to the specific type needing the cast.

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

Navbar Growth Effect

I'm attempting to create an expanding effect in my navbar using Angular. When I click on "show information," the content should slide up. The issue is that the top part of my footer does not follow the effect. I have tried something like: <foot ...

Creating a Circle with Pixi.js v4 and Typerscript in IONIC 2

I have been attempting to create a custom class in TypeScript that utilizes PIXI.js to draw circles. Below is the code for my home.ts class: import { Component, ViewChild, ElementRef } from '@angular/core'; import { NavController } from 'i ...

Encountered an issue while attempting to authenticate CMS signature using pkijs

I am attempting to validate a CMS signature generated with open ssl using the following command: $ openssl cms -sign -signer domain.pem -inkey domain.key -binary -in README.md -outform der -out signature Below is my code utilizing pkijs: import * as pkij ...

I am unable to utilize the outcome of a custom hook within a function or within an effect hook

I've developed a unique custom hook that retrieves a list of individuals File: persons.hooks.ts import {useEffect, useState} from "react"; import Person from "../../models/person/Person"; const usePersons = () => { const ...

Removing curly braces and double quotes from an array object can be achieved by iterating through each element

Within this particular project, I have utilized Angular 8 and TypeScript. In the implementation, there exists an array that showcases emails either through user input or via CSV upload. Once the user inputs several emails, a button is available to send in ...

Encountering difficulty when trying to initiate a new project using the Nest CLI

Currently, I am using a tutorial from here to assist me in creating a Nest project. To start off, I have successfully installed the Nest CLI by executing this command: npm i -g @nestjs/cli https://i.stack.imgur.com/3aVd1.png To confirm the installation, ...

Tips on maintaining the chosen product while navigating to a different component

I have a dilemma with 2 different components that are responsible for creating an invoice. The first component adds more products The second component adds invoice details Initially, I enter the invoice details and select the client's name. The sel ...

An issue with TypeORM syntax causing errors within a NestJS migration file

I recently encountered an issue while setting up PostgreSQL with NestJS and TypeORM on Heroku. Despite successfully running a migration, my application kept crashing. I attempted various troubleshooting methods by scouring through blogs, GitHub issues, and ...

Why am I encountering numerous errors while attempting to install Juice Shop?

My attempt to install the juice shop app from GitHub resulted in 63 errors showing up after running the command npm install. [riki@anarchy]: ~/juiceShop/juice-shop>$ npm install (Various warnings and engine compatibility issues) Multiple vulnerabilit ...

Guide to accessing the content of pure ES6 modules directly in the Chrome console without the need for Webpack

Situation: When using tsc to compile code for es6, the scripts function properly once they are served from a server. However, I am unsure of how to access variables within modules through the console. The file names do not seem to be available as objects ...

What is the method to access an interface or type alias that has not been explicitly exported in TypeScript type definitions?

I am looking to create a new class that inherits from Vinyl. The constructor in the superclass takes a single parameter of type ConstructorOptions. export default class MarkupVinylFile extends Vinyl { public constructor(options: ConstructorOptions) { ...

After compiling, global variables in Vue.js 2 + Typescript may lose their values

I am currently working on a Vue.js 2 project that uses Typescript. I have declared two variables in the main.ts file that I need to access globally throughout my project: // ... Vue.prototype.$http = http; // This library is imported from another file and ...

Hidden input fields do not get populated by Angular submit prior to submission

I am in the process of implementing a login feature in Angular that supports multiple providers. However, I have encountered an issue with submitting the form as the loginProvider value is not being sent to the server. Below is the structure of my form: &l ...

When attempting to pass an array of objects to a child component, TypeScript raises an error regarding types

Hey everyone, I'm currently facing an issue while trying to pass an array of objects as props. Here's the content of my data.json file: [ { "category": "Reaction", "score": 80, "icon": " ...

Getting the value of the chosen option from one component and passing it to another component in Angular 8

How can I pass the selected option value from the login component to the home component without using local storage? When an option is selected in the login component, I want that value to be displayed in the home component. Below is the code snippet: Lo ...

Getting pictures dynamically from the backend with unspecified file types

Greetings to my fellow Stackoverflow-Users, Lately, I was tasked with the requirement of loading images dynamically from the backend into my application. Up until now, it was always assumed that we would only be dealing with SVG images since there was no ...

Navigational bar mishaps: troubleshooting the "is not a function error" in layout.tsx

I recently started learning React (Next.js) and I'm working on adding a navbar feature to my project. The goal is to have the active navlink stand out when the user is on the corresponding page. To achieve this, I created a function that updates the s ...

React is running smoothly, however, when attempting to call the React flow, an error is encountered: "Error: (0 , react__WEBPACK_IMPORTED_MODULE_0__.createContext) is not

Recently, I set up a React application using Next.js and TypeScript. Initially, everything was running smoothly with the command npm run dev. However, upon integrating the react flow library with npm install reactflow, I encountered an error when trying to ...

Tips for waiting for an Http response in TypeScript with Angular 5

Is it possible to create a function that can retrieve a token from a server, considering that the http.post() method generates a response after the function has already returned the token? How can I ensure that my function waits for the http.post() call t ...

Add a custom design to the Material UI menu feature

I am currently trying to implement a custom theme using the following code: import Menu from '@material-ui/core/Menu'; import { createStyles, withStyles, Theme } from '@material-ui/core/styles'; const myMenu = withStyles( ( theme: The ...