MoreThanTom
MoreThanTom

Reputation: 526

Generic static class method

How can you type a method which uses a static property on extended classes?

Given the javascript:

class Animal {}
Animal.makeNoise = (language) => this.sounds[language];

class Dog extends Animal {}
Dog.sounds = {
  english: 'woof-woof',
  portuguese: 'au-au'
}

I thought this might work

abstract class Animal {
  static sounds: { [key in string]: false | string[] | string }
  static makeNoise
    = <S extends typeof Dog.sounds, L extends keyof S>(language: L): S[L]
      => this.sounds[language];
}
class Dog extends Animal {
  static sounds: {
    english: 'woof-woof',
    portuguese: 'au-au'
  }
}
Dog.makeNoise('english') // => "woof-woof"

But I cant find a way to reference the this.sounds of every extended class. Is there any right way to do this yet?

Upvotes: 1

Views: 75

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250406

Since you want the static method to work for any derived classes you can use the this parameter to capture the actual type of sound in the derived class. You can then use this type information to extract the actual sound type:

abstract class Animal {
    static sounds: Record<string, false | string[] | string>
    static makeNoise<TSounds extends typeof Animal['sounds'], L extends keyof TSounds>(this: { sounds: TSounds }, language: L): TSounds[L] {
        return this.sounds[language];
    }
}
class Dog extends Animal {
    static sounds: {
        english: 'woof-woof',
        portuguese: 'au-au'
    }
}
Dog.makeNoise('english') // => "woof-woof"

Upvotes: 2

Related Questions