title: Communicating types between static and instance class members, while extending
body: <p>In the following example, I create a "bundle" which contains a react context AND a react class which renders a provider for this context. This "bundle" accepts some parameters, in this case expressed as (abstract) class properties to be overriden.</p>
  
  <p>(could also use more functional patterns, i'm open to whatever pattern allows me to leverage the maximum possible of inference and extension)</p>
  
  <p>The context is meant to be a "static-y" property, but its type depends on an instance property. I've been having difficulty on inferring the static context type from a type owned by the "instance side" of the class.</p>
  
  <p>I ended up with a hack as described below, where the derived classes need to receive a <code>Self</code> type parameter and the context has to be accessed from <code>Derived.prototype.getContext()</code>. While this works, it is hacky, I'd like to know if I could avoid it.</p>
  
  <pre><code>type State&lt;EntityType&gt; = { hey: EntityType; ready: boolean }
  abstract class CrudDetail&lt;
    EntityType extends Object,
    Self extends CrudDetail&lt;any, any&gt;
  &gt; extends React.PureComponent&lt;{}, State&lt;EntityType&gt;&gt; {
    state = {
      ready: false,
      hey: {} as EntityType,
    }
  
    // exampĺes of possible parameters
    abstract entityName: string
  
    // this is meant to be overriden 
    // the context is tied on the instance state
    getContextValue() {
      return {
        hey: this.state.hey,
      }
    }
  
    // the type of this property depends on instance.getContextValue()
    // how can i access it from here?
    private static context = React.createContext({})
  
    // only instance members can access type parameters
    // so I came up with an instance member and a Self
    // type parameter to access the derived class type
    // This is kinda ugly and is the thing I'd like to avoid.
    getContext() {
      return (this.constructor as any).context as React.Context&lt;ReturnType&lt;Self['getContextValue']&gt;&gt;
    }
  
    render() {
      return (
        &lt;CrudDetail.context.Provider value={this.getContextValue()}&gt;
          {this.props.children}
        &lt;/CrudDetail.context.Provider&gt;
      )
    }
  }
  </code></pre>
  
  <p>consuming</p>
  
  <pre><code>type Person = { name: string }
  
  class PersonCrud extends CrudDetail&lt;Person, PersonCrud&gt; {
    state = {
      ...super.state,
      name: "",
    }
  
    getContextValue = () =&gt; {
      let that = this
      return extend(super.getContextValue(), {
        name: this.state.name,
        heyreadyName() {
          return that.state.ready &amp;&amp; this.hey &amp;&amp; this.name
        },
      })
    }
  }
  
  const Test2 = () =&gt; {
    const Ctx = PersonCrud.prototype.getContext()
    return (
      &lt;PersonCrud&gt;
        &lt;Ctx.Consumer&gt;{ctx =&gt; &lt;div&gt;{ctx.heyreadyName()}&lt;/div&gt;}&lt;/Ctx.Consumer&gt;
      &lt;/PersonCrud&gt;
    )
  }
  </code></pre>
  
  <p>(<code>extend</code> comes from <a href="https://stackoverflow.com/questions/51900537/extending-the-inferred-this">Extending the inferred &quot;this&quot;</a>)</p>
  
  <p>Reiterating, is it possible that I can:</p>
  
  <ul>
  <li>Establish a contract of parameters the base class needs to implement (either through classes, closures, or whatever)</li>
  <li>Have the contract implementations be type-safe</li>
  <li>Have the consuming context <code>&lt;Context.Consumer&gt;</code> correctly typed</li>
  <li>Be DRY. My approach still had the non-DRYness for needing to provide the <code>Self</code> type parameter, and the "this.constructor" hack</li>
  </ul>
  
  <p>(i'd paste a codesandbox but infortunately it is still stuck on TS 2.7...)</p>