Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A 'this' type is available only in a non-static member of a class or interface

I'm trying to define a class where one of the constructor parameter property declares and initializes a public member of type (this: this) => string and I'm getting a A 'this' type is available only in a non-static member of a class or interface error.

This doesn't generate and error:

interface Foo {
    name: string; 
    isLocked: boolean;
    destination: string;
    description: (this: this) => string; 
}

const foo: Foo = {
    name: 'newdoor',
    isLocked: true,
    destination: 'someroom',
    description: function(this) {
        if(this.isLocked) return 'true'
        else return 'false'
    }
}

But this does:

class Bar {
    constructor(
        public name: string, 
        public isLocked: boolean,
        public destination: string,
        public description: (this: this) => string
    ) {}    
}

const bar = new Bar(
    'newdoor',
    true,
    'someroom',
    function(this) {
        if(this.isLocked) return 'true'
        else return 'false'
    }
)

Can someone explain why I'm getting this error even though I am indeed using the this type in a non-static member of a class? Also, if this is by design and there is a reason for this error, what is the work around in order to be able to create a class instance and supply it with a member function that has access to the class instance.

Update

As explained in the provided answers, it seems that the use of this is not allowed in a constructor parameter property. But this leaves the question, how then, can I create a class instance, where one of the property parameters declares and initializes a member that is a function that needs access to the instance's other members?

If I do this:

class Bar {
    constructor(
        public name: string, 
        public isLocked: boolean,
        public destination: string,
        public description: () => string
    ) {}    
}

const bar = new Bar(
    'newdoor',
    true,
    'someroom',
    function() {
        if(this.isLocked) return 'true'
        else return 'false'
    }
)

I then get a 'this' implicitly has type 'any' because it does not have a type annotation error. This is valid JavaScript code and does what I expect it to do. What is the proper TypeScript way to code this?

like image 440
snowfrogdev Avatar asked Oct 16 '25 22:10

snowfrogdev


1 Answers

The error message is misleading and I don't know why the first example doesn't generate an error. But your problem in the second example is actually that you are trying to use this as a type describing the value this. In the signature you have type the this parameter to be of the type it will be. In your case it would have to be

(this: Bar) => string

Also this parameters are fake parameters that only tell TypeScript the type this will have in the function body. It is not a parameter you would pass to as an argument. Read about it in the docs.

You can actually omit the this parameter from the function you are passing when you create a new instance because TypeScript can infer the type of this from the function signature in the class constructor definition.

Update

As explained in the provided answers, it seems that the use of this is not allowed in a constructor parameter property.

Apparently my answer was not clear, sorry. Of course this allowed. But you were trying to do this:

(this: this) => string

That tells TypeScript that this (on the left) in the function body is of type this (on the right). But there is no type called this in TypeScript and it is not allowed to declare one because it is a reserved keyword. As I said above you have to declare this to be of type Bar.

Here is the full example:

class Bar {
    constructor(
        public name: string, 
        public isLocked: boolean,
        public destination: string,
        public description: (this: Bar) => string
    ) {}    
}

const bar = new Bar(
    'newdoor',
    true,
    'someroom',
    function() {
        if(this.isLocked) return 'true'
        else return 'false'
    }
)
like image 87
Tao Avatar answered Oct 18 '25 13:10

Tao