1

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.

Aluan Haddad
  • 29,886
  • 8
  • 72
  • 84
dcsan
  • 11,333
  • 15
  • 77
  • 118
  • 1
    `Mouth` is the type of the instances. The class itself is `typeof Mouth`. i.e. you need to say: `mouth: typeof Mouth` – ccarton Oct 08 '20 at 15:04

1 Answers1

2

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')
  }
}
Christoph Lütjen
  • 5,403
  • 2
  • 24
  • 33
  • got it thanks! `mouth: Mouth` is a setup for an instance of Mouth, not the Mouth class itself. `mouth = Mouth` does the assignment and lets TS handle the types. – dcsan Oct 09 '20 at 15:05
  • 1
    I've added some more comments to make it more obvious in code. – Christoph Lütjen Oct 09 '20 at 15:51