Skip to content

typeof this.xxx gives "identifier expected" error. #1554

Closed

Description

@vilicvane

image

Is this by design or a bug?

Activity

  1. giancarloa commented on Dec 24, 2014

    @giancarloa

    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...

  2. vilicvane commented on Dec 24, 2014

    @vilicvane
    Author

    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 = {};
        }
    }
  3. DanielRosenwasser commented on Dec 26, 2014

    @DanielRosenwasser
    Member

    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.

  4. vilicvane commented on Dec 26, 2014

    @vilicvane
    Author

    Daniel Rosenwasser (@DanielRosenwasser) O.O hmm... then hoping you would consider updating the spec. lol.

  5. DanielRosenwasser commented on Dec 27, 2014

    @DanielRosenwasser
    Member

    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;
  6. NN--- commented on Dec 29, 2014

    @NN---

    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.

  7. RyanCavanaugh commented on Dec 30, 2014

    @RyanCavanaugh
    Member

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

  8. DanielRosenwasser commented on Dec 30, 2014

    @DanielRosenwasser
    Member

    Ryan Cavanaugh (@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.

  9. vilicvane commented on Dec 30, 2014

    @vilicvane
    Author

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

  10. RyanCavanaugh commented on Dec 30, 2014

    @RyanCavanaugh
    Member

    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.

  11. juanevp commented on Feb 3, 2015

    @juanevp

    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.

  12. mwisnicki commented on Mar 29, 2015

    @mwisnicki

    Juan Vidal Pich (@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>;
    }
  13. 6 remaining items

  14. sam-s4s commented on Feb 5, 2018

    @sam-s4s

    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.

    Ryan Cavanaugh (@RyanCavanaugh) Daniel Rosenwasser (@DanielRosenwasser) Mohamed Hegazy (@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?

  15. weswigham commented on Feb 5, 2018

    @weswigham
    Member

    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.

  16. sam-s4s commented on Feb 5, 2018

    @sam-s4s

    Thanks Wesley Wigham (@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...

  17. yxliang01 commented on Jul 17, 2019

    @yxliang01

    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"?

  18. vegerot commented on Jun 8, 2020

    @vegerot

    If I have something like

      public groupByTypes = ['None', 'Foo', 'Bar'] as const;
       
      public groupBy: typeof groupByTypes[number];

    What is the proposed workaround? And I cannot make groupByTypes static

  19. Feofilakt commented on Apr 6, 2021

    @Feofilakt

    OMG, 7 years old design bug. Ok, see what would be after yet another 7.

  20. ubershmekel commented on Apr 25, 2021

    @ubershmekel
    Contributor

    My use-case is I'm sending a callback to a library which has the wrong type specialization. I also don't want to have to remember this spot in the code in case these variables ever change their type. So it looks like

      async foundBob(playerTypeLess: any, bobTypeLess: any) {
        const player = playerTypeLess as typeof this.player;
        ^^ ts(2304) Cannot find name 'this'.
    

    I do use this later in that same method. So the error message is a bit misleading. I end up doing the simpler but more fragile:

        const player = playerTypeLess as Player;
    
  21. Zzzen commented on Apr 30, 2021

    @Zzzen
    Contributor

    Have you tried const player = playerTypeLess as this['player'] ? Yuval Greenfield (@ubershmekel)

  22. royeradames commented on Jan 13, 2022

    @royeradames

    Have you tried const player = playerTypeLess as this['player'] ? Yuval Greenfield (@ubershmekel)

    TS2304: Cannot find name 'this'.

    243 selectedPlanFilters? = [] as typeof this["filters"];

  23. muuvmuuv commented on Oct 1, 2023

    @muuvmuuv

    I get no errors for this in VS Code but from the Angular compiler. Did anyone has a workaround for TS2304? I would like to have FormGroup.value typed in ngSubmit function with typeof this.formGroup.value.

  24. Xriuk commented on Apr 17, 2024

    @Xriuk

    I get no errors for this in VS Code but from the Angular compiler. Did anyone has a workaround for TS2304? I would like to have FormGroup.value typed in ngSubmit function with typeof this.formGroup.value.

    More or less the same, it used to work while on Angular 14 (also tried with Angular 15), but with Angular 16 it compiles, then after a save it recompiles partially and this error pops up.

  25. serious-angel commented on May 6, 2024

    @serious-angel

    Is an explicit type an option? It seems like a cleaner version. For example, with TypeScript utility type Record (Repl):

    type SomeType = Record<string, string>;
    //   ^? type SomeType = { [x: string]: string; }
    
    class Test {
        static data1: SomeType = {};
        //     ^? (property) Test.data1: SomeType
    
        data2: SomeType = {};
        // ^? (property) Test.data2: SomeType
    
        constructor() {
            let copy1: SomeType = {};
            //  ^? let copy1: SomeType
    
            let copy2: typeof Test.data1 = {};
            //  ^? let copy2: SomeType
    
            let copy3: typeof this.data2 = {};
            //  ^? let copy3: SomeType
        }
    }

    JavaScript Declarations
    class Test {
        constructor() {
            this.data2 = {};
            let copy1 = {};
            let copy2 = {};
            let copy3 = {};
    
        }
    }
    
    Test.data1 = {};
    type SomeType = Record<string, string>;
    
    declare class Test {
        static data1: SomeType;
        data2: SomeType;
        constructor();
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions