The type named MyClass corresponds to an instance of the MyClass class, and as such does not have the static methods such as x or y.
Inside a static method implementation, this refers to the constructor itself, which (as long as you don't have subclasses to worry about) will be the value named MyClass. The type of the MyClass constuctor is not MyClass, but typeof MyClass, using the Typescript typeof type query operator.
If you use IntelliSense to inspect the return types inferred for x() and y() in your example code, you'll see:
class MyClass {
// (method) MyClass.x(): typeof MyClass
// ↓
static x() {
console.log("x");
return this;
}
}
If you really want to annotate the type for some reason, typeof MyClass is potentially the right answer:
class MyClass {
static x(): typeof MyClass {
console.log("x");
return this;
}
static y(): typeof MyClass {
console.log("y");
return this;
}
}
Note that things get a bit trickier if you have subclasses and you want to capture the fact that subclasses have inheritance on the static side too:
class YourClass extends MyClass {
static z = 123;
}
YourClass.x().z // error!
// ---------> ~
// not known to exist by TypeScript but exists at runtime
You probably don't care about that, but if you do it's an outstanding issue in TypeScript; see microsoft/TypeScript#5863 for discussion and workarounds. More information available upon request.
Playground link to code
typeof MyClass, which is what you could annotate it as, if you really want to.