Is this by design or a bug?
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 withthis
(a polymorphic one, even), unliketypeof
.
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 make
groupByTypes` static
Most helpful comment
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 thatthis
should work, instead of only able to use the "ClassName"?