1

Image I have this little class with 2 static methods. Like this I can chain the methods as I want.

class MyClass {
  static x() {
    console.log("x");
    return this;
  }

  static y() {
    console.log("y");
    return this;
  }
}

MyClass.x().y();

If I wanted to add typings for the 2 methods how would the typings look like? In other words how can I define the correct return type?

class MyClass {
  static x(): MyClass {
    console.log("x");
    return this;
  }

  static y(): MyClass {
    console.log("y");
    return this;
  }
}

MyClass.x().y();

This doesn't work but hopefully shows what I mean.

2
  • 3
    Why do you need to define any type? Let the compiler infer it as typeof MyClass, which is what you could annotate it as, if you really want to. Commented Feb 14, 2021 at 18:49
  • I know it does work without defining a type but i just want to have it there. OMG Thanks! literally forgot the typeof :| Commented Feb 14, 2021 at 18:55

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.