typescripttypescript2.4

How to tell typescript to get generic type from argument object?


Say I have following definition:

interface Options<T = any, K = void> {
  scope?: K,
  success: (this: K, result: T) => any,
  failure: (this: K, result: T) => any
}

interface HttpClient {
  request<T>(opts: Options<T>)
}

From above definition, typescript wont give me correct type for this in success & failure. How do I tell Typescript that K should be scope property of the first argument.

Example usage:

class Abc {
  //...

  save() {
    var client = new HttpClient()
    client.request({
      scope: this,
      success: function(result) {
        this // here no intellisense
      }
    })
  }

  notify(event, data) {
    this.element.dispatchEvent(new CustomEvent(event, { detail: data }));
  }
}

Solution

  • When you declare request<T>(opts: Options<T>) you are fixing the type K with its default value void. If you want to keep that type variable as something variable it must still be a type parameter in request<T,K>.

    This code correctly deduces the type of this as this:

    interface Options<T = any, K = void> {
      scope?: K,
      success: (this: K, result: T) => any,
      failure?: (this: K, result: T) => any
    }
    
    class HttpClient {
      request<T, K>(opts: Options<T, K>) : any {}
    }
    
    class Abc {
      //...
    
      save() {
        var client = new HttpClient()
        client.request({
          scope: this,
          success: function(result) {
            this // here intellisense offers `notify` and `save` completion
          }
        })
      }
    
      notify(event, data) {
        this.element.dispatchEvent(new CustomEvent(event, { detail: data }));
      }
    }
    

    Other minor code changes: I had to make failure optional and HttpClient a class just for the purposes of getting some code that doesn't complain about anything higher up than notify().