Typescript: typeof this.xxx gives "identifier expected" error.

Created on 24 Dec 2014  ·  19Comments  ·  Source: microsoft/TypeScript

image

Is this by design or a bug?

Suggestion help wanted

Most helpful comment

@sam-s4s nowdays you aught to be able to write CMultiDataset<this["thing"]>, instead. Indexed acceses _do_ work with this (a polymorphic one, even), unlike typeof.

I have just tried, but it doesn't work in TypeScript 3.4.4 though, @sam-s4s 's one works (ClassName['thing']). I think it might make more sense that this should work, instead of only able to use the "ClassName"?

All 19 comments

i would say neither... it's just wrong syntax... try " var copy = typeof (this.data = { });"... having said this, i would not use this code... it's confusing...

@giancarloa hmm, you shouldn't add those brackets. the code above is just a minimum issue trigger, not code in production, there would be some situations that you may want to use code like this.

here if you take this to anything other than that, it would be fine and no error would be reported. e.g.

class Test {
    static data = {};
    constructor() {
        var copy: typeof Test.data = {};
    }
}

As per the spec

_TypeQueryExpression:_
 _Identifier_
 _TypeQueryExpression_ . _IdentifierName_

So this is expected.

I think the reason it isn't allowed is that something like this

function foo() {
    var x: typeof this.x;
}

is perfectly valid, because this more or less has type any. So while it might make sense in a class, it doesn't make sense in any other context unless we had #229.

@DanielRosenwasser O.O hmm... then hoping you would consider updating the spec. lol.

It's something to consider; if your members are not private, you can easily get around this with the following in the mean time.

self = this;
var x: typeof self.data;

Waiting for this feature.
I think the simplest case should be supported
var a : typeof this.x = 1;

And a recursive typeof member should lead to error.

Thanks.

Seems like this should just work if we changed the grammar.

@RyanCavanaugh, but is it appropriate to allow it in the context I gave? It will inevitably lead to people doing so and getting any as their type.

syntactically correct doesn't have to mean that it should actually make sense, IMO.
a warning could be raised for this cause, though.

We already let you write typeof foo.bar where foo is of type any, and we already let you write this.x in other dotted-expression positions when the type of this is any. I don't see why their intersection at typeof this.x should merit an exception.

Just to add another use case. Some time ago I made the type definitions for lodash and some of the supported signatures are really aliases for other methods. I had declared them like this:

interface LoDashArrayWrapper<T> {
    rest(): LoDashArrayWrapper<T>;
    rest(
        callback: ListIterator<T, boolean>,
        thisArg?: any): LoDashArrayWrapper<T>;
    rest(n: number): LoDashArrayWrapper<T>;
    rest(pluckValue: string): LoDashArrayWrapper<T>;
    rest(whereValue: {}): LoDashArrayWrapper<T>;

    drop: typeof rest;

    tail: typeof rest;
}

This worked alright with version 1.0 of the compiler. But it doesn't compile any longer. And I don't see any other option besides duplicating the whole set of signatures for each alias as I cannot think of a TypeQueryExpression that expresses this.

@juanevp How about function interface ?

interface LoDashArrayWrapper<T> {
    rest: LoDashArrayWrapperOperation<T>;
    drop: LoDashArrayWrapperOperation<T>;
    tail: LoDashArrayWrapperOperation<T>;
}

interface LoDashArrayWrapperOperation<T> {
    (): LoDashArrayWrapper<T>;
    (
        callback: ListIterator<T, boolean>,
        thisArg?: any): LoDashArrayWrapper<T>;
    (n: number): LoDashArrayWrapper<T>;
    (pluckValue: string): LoDashArrayWrapper<T>;
    (whereValue: {}): LoDashArrayWrapper<T>;
}

Approved. Should be extremely easy fix? Make sure this doesn't cause _this = this emit in arrow functions, though

Is this related? I get [ts] Identifier expected. with following:


class UserState {
    @observable state = {
        name : "",
        id : "",
    };

    @action
    changeUser(user: typeof this.state) { // Error is here
        Object.assign(this.state, user);
    }
}

export const userState = new UserState();

It would be useful to be able to use this.state in above case.

Hmmm I've just run into this problem :(

I'm defining an object in my class.
Then I'm defining another object that has a type param that needs to be the type of the above.

thing = {
    a: 1,
    b: 2
};
multi: CMultiDataset<typeof this.thing>;

In this case it is not appropriate to just change thing to a static variable and say typeof ClassName.thing because it will be different in each instance. Also multi needs to be a class variable, and thus must have its type in class declaration time.

@RyanCavanaugh @DanielRosenwasser @mhegazy sounds like this was thought to be a relatively easy fix? Looks like it's slipped away from attention over the years though... Any chance of it being implemented?

@sam-s4s nowdays you aught to be able to write CMultiDataset<this["thing"]>, instead. Indexed acceses _do_ work with this (a polymorphic one, even), unlike typeof.

Thanks @weswigham - I did find out that I can do CMultiDataset<ClassName['thing']> which mostly gets me out of trouble :)

I could not find any combination using this that would work though...

@sam-s4s nowdays you aught to be able to write CMultiDataset<this["thing"]>, instead. Indexed acceses _do_ work with this (a polymorphic one, even), unlike typeof.

I have just tried, but it doesn't work in TypeScript 3.4.4 though, @sam-s4s 's one works (ClassName['thing']). I think it might make more sense that this should work, instead of only able to use the "ClassName"?

If I have something like
```typescript
public groupByTypes = ['None', 'Foo', 'Bar'] as const;

public groupBy: typeof groupByTypes[number];
`` What is the proposed workaround? And I cannot makegroupByTypes` static

Was this page helpful?
0 / 5 - 0 ratings

Related issues

CyrusNajmabadi picture CyrusNajmabadi  ·  3Comments

MartynasZilinskas picture MartynasZilinskas  ·  3Comments

wmaurer picture wmaurer  ·  3Comments

siddjain picture siddjain  ·  3Comments

bgrieder picture bgrieder  ·  3Comments