title: How to handle static generic property inheritance in Typescript?
body: <p>I'm trying to model a shallow class based interface to Firestore objects to encapsulate the custom object converters. Consider two classes with custom converters and collection name with a common <code>docRef</code> function, they may have other properties than just a single string:</p>
  <pre class="lang-js prettyprint-override"><code>class Foo {
    constructor(public fooVal: string) {}
  
    // Table / collection specific functions bound to this model
    static #firestoreConverter: FirestoreDataConverter&lt;Foo&gt; =
      {
        toFirestore(modelObject) {
          return {
            fooVal: modelObject.fooVal,
          };
        },
        fromFirestore(snapshot, options?) {
          const data = snapshot.data(options);
          return new Foo(data.fooVal);
        },
      };
    static #collectionName = &quot;Foo&quot;;
    // --- Refactor from here on ---
    static #collection = collection(db, this.#collectionName).withConverter(
      this.#firestoreConverter
    );
  
    static docRef(id: string) {
      return doc(this.#collection, id);
    }
  }
  
  class Bar {
    constructor(public barVal: string) {}
  
    // Table / collection specific functions bound to this model
    static #firestoreConverter: FirestoreDataConverter&lt;Bar&gt; =
      {
        toFirestore(modelObject) {
          return {
            barVal: modelObject.barVal,
          };
        },
        fromFirestore(snapshot, options?) {
          const data = snapshot.data(options);
          return new Bar(data.barVal);
        },
      };
    static #collectionName = &quot;Bar&quot;;
    static #collection = collection(db, this.#collectionName).withConverter(
      this.#firestoreConverter
    );
  
    static docRef(id: string) {
      return doc(this.#collection, id);
    }
  }
  </code></pre>
  <p>I can't resolve the type dependent converter property (<code>firestoreCoverter</code> return type depends on the specific class). An inheritance based solution gets stuck because the return type is the type of the child not the parent but we don't know what type the child is until the child is created. For example:</p>
  <pre class="lang-js prettyprint-override"><code>abstract class BaseModel {
    static collectionName: string;
    // Here, the type of firestoreConverter will change in the child class
    static firestoreConverter: FirestoreDataConverter&lt;BaseModel&gt;;
  
    static docRef(id: string) {
      const col = collection(db, this.collectionName).withConverter(
        this.firestoreConverter
      );
      return doc(col, id);
    }
  }
  
  // If you inherit, e.g. Foo extends BaseModel
  // We get Foo.docRef type to be FirestoreDataConverter&lt;BaseModel&gt;
  // even though Foo.converter is of type FirestoreDataConverter&lt;Foo&gt;
  </code></pre>
  <p>Mixin based also struggles with the return type of the converter property. Is there a type safe and elegant way to refactor these two classes?</p>