New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[no-invalid-void-type] Should allow this: void #2148
Comments
This code doesn't do what you think it does - defining an interface method with interface ClassWithStaticMethod {
method(this: void): void;
}
class Foo implements ClassWithStaticMethod {
foo = 1;
method() { // no error
console.log(this.foo); // can still use `this`
}
}
Foo.method(); // error - Property 'method' does not exist on type 'typeof Foo'.
(new Foo()).method();
class Bar implements ClassWithStaticMethod { // error - Property 'method' is missing in type 'Bar' but required in type 'ClassWithStaticMethod'.
static foo = 1;
static method() { // no error
console.log(this.foo); // can still use `this`
}
}
const x = {
foo: 1,
method() {
console.log(this.foo);
},
}
const y: ClassWithStaticMethod = x; // no error
y.method(); |
Oh, huh. I remember having cases where I had to use |
note that static methods still have access to a class Foo {
static one() {
this.two();
}
static two() {
console.log('two');
}
}
Foo.one(); // prints "two" TBH Also, you should avoid |
Another use case: interface Options {
[key: string]: any
setup: (this: void) => any
}
const defineComponent = (options: Options) => {
const { setup } = options
setup()
}
defineComponent({
setup() {
console.log(this.a) // won't report error without `this: void`
}
}) |
TBF though - for that use case it wouldn't matter if the function was on a class or an object, it would error at runtime. Additionally using Eg this is valid code, that will circumvent the interface Options {
[key: string]: any
setup: (this: void) => any
}
const defineComponent = (options: Options) => {
const { setup } = options
setup()
}
class Foo implements Options {
setup() {
console.log(this.a);
}
[key: string]: any;
}
defineComponent(new Foo()) IMO that use case is an edge case that should be covered with an We've thought about introducing a lint rule to always require I just advise against ever using |
Personally, I think that |
happy to accept a PR if someone wants to implement it. |
typescript explicitly recommends using If a subclass overrides a method without explicit Also the implementation of typescript does use the // line 15677
if (sourceThisType && sourceThisType !== voidType){}
// line 25918
const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType;
// line 26152
if (thisType && thisType !== voidType && ...){} So highly in support of allowing void on the this parameter and will start working on a PR. |
Hmm, interesting, do you know why this happens? Is this a bug? |
@papb no it's just that the logic to actually check the this parameter is comparatively time consuming, having using the I'm sure it'd be possible for typescript to make optimizations to speed this up in trivial cases like |
It's just a limitation of how TS handles IIRC - when you annotate a method with a I can't recall the issues off the top of my head, but I've seen it discussed in the past - people have asked for lint rules and TS features that make you always annotate the |
@bradzacher no you are thinking of the When you use a class method like: class Example {
method(): this { return this; }
} it internally handles it similar to: class Example2 {
method<T extends Example2>(this: T): T {return this;}
} just adding a parameter for particularly for |
Found the issue: microsoft/TypeScript#35451 (comment) Quoting the comment:
|
Repro
Expected Result: Should not return an error here, as
this: void
clarifies that the method is static.Actual Result: Throws an error saying that void is only valid as a return type or generic type variable.
Additional Info: TypeScript specially refers to "this in void context" which clarifies that
void
is the right type here, notundefined
.Versions
@typescript-eslint/eslint-plugin
2.34.0
@typescript-eslint/parser
2.34.0
TypeScript
3.9.3
ESLint
7.0.0
node
12.16.3
yarn
1.22.4
The text was updated successfully, but these errors were encountered: