bigopon
bigopon

Reputation: 1974

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 }));
  }
}

Upvotes: 1

Views: 902

Answers (1)

Duncan
Duncan

Reputation: 95722

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().

Upvotes: 1

Related Questions