Search code examples
javascripttypescriptstaticsubclass

using static class methods in another class in typescript


I want to use certain static methods from another class in my code, but getting a weird error.

class Mouth {
  static greet() {
    console.log('Mouth.greet')
  }
}

class DogMouth extends Mouth {
  static greet() {
    console.log('DogMouth.woof')
  }
}

class Animal {
  mouth: Mouth
  constructor() {
    this.mouth = Mouth
  }

  greet() {
    this.mouth.greet()  // fails with Property 'greet' is a static member of type 'Mouth'
    Mouth.greet() // this works but should be the same thing?
    console.log('Animal.greet')
  }

}

class Dog extends Animal {

  constructor() {
    super()
    this.mouth = DogMouth
  }
}

function main() {
  const pup = new Dog()
  pup.greet()
}

main()

I created a typescript playground example here

So these are the problem lines, where this.mouth is defined to be the class Mouth collapsing the constructor etc code its the same as this:

    this.mouth = Mouth
    this.mouth.greet()  // fails with Property 'greet' is a static member of type 'Mouth'
    Mouth.greet() // this works but should be the same thing?

If this is confusing I'm wondering what better patterns I could use where I need certain methods to do different things based on the subclass. But ideally those methods are also available as static methods outside the subclass.


Solution

  • You declared your property to be an instance of Mouth

    mouth: Mouth
    

    ... but static methods are not available on instances

    Static methods aren't called on instances of the class. Instead, they're called on the class itself

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static

    So the soultion is, to set the correct type or let TS do it for you:

    class Animal {
      // TS will detect type from assignment
      mouth = Mouth;
    
      // Set type manually and assign
      // mouth: typeof Mouth = Mouth;
    
      // Set type only (and assign later)
      // mouth: typeof Mouth;
    
      // NOT WHAT YOU WANT (instance, static methods not available)
      // mouth: Mouth = new Mouth();
    
      greet() {
        this.mouth.greet()
        Mouth.greet()
        console.log('Animal.greet')
      }
    }