title: How can I declare a function that optionally takes a callback, and returns a Promise only if there is no callback?
body: <p>TypeScript v2.0.2
  on a Mac running El Capitan 10.11.6</p>
  
  <p>I have a single function that performs an async operation,
  and:</p>
  
  <ul>
  <li>either takes a callback, and returns nothing, calling the callback
  later,</li>
  <li>or doesn't take a callback, and returns a Promise, that resolves later.</li>
  </ul>
  
  <p>It seems that I've been had similar code work,
  (see <a href="https://github.com/psnider/mongodb-adaptor/blob/master/src/ts/MongoDBAdaptor.ts" rel="nofollow">https://github.com/psnider/mongodb-adaptor/blob/master/src/ts/MongoDBAdaptor.ts</a>)
  but right now this is failing, 
  and I can't figure out why!</p>
  
  <pre><code>// these declarations look correct to me, the caller uses one or the other
  declare abstract class SlimDocumentDatabase&lt;T&gt; {
      create(obj: T): Promise&lt;T&gt;
      create(obj: T, done: (error: Error, result?: T) =&gt; void): void
  }
  
  class SlimAdaptor&lt;DocumentType&gt; implements SlimDocumentDatabase&lt;DocumentType&gt; {
      create(obj: DocumentType, done?: (error: Error, result?: DocumentType) =&gt; void) : void | Promise&lt;DocumentType&gt; {
          if (done) {
              done(undefined, obj)
              return
          } else {
              return Promise.resolve&lt;DocumentType&gt;(obj)
          }
      }
  }
  </code></pre>
  
  <p>I can get this to compile by removing the return type specifications from the implementation of create(), by replacing them with <strong>any</strong>. But this seems so wrong!</p>
  
  <p>Here is the code in the TypeScript Playground:
  <a href="http://www.typescriptlang.org/play/index.html#src=declare%20abstract%20class%20SlimDocumentDatabase%3CT%3E%20%7B%0A%20%20%20%20create(obj%3A%20T)%3A%20Promise%3CT%3E%0A%20%20%20%20create(obj%3A%20T%2C%20done%3A%20(error%3A%20Error%2C%20result%3F%3A%20T)%20%3D%3E%20void)%3A%20void%0A%7D%0A%0A%0Aclass%20SlimAdaptor%3CDocumentType%3E%20implements%20SlimDocumentDatabase%3CDocumentType%3E%20%7B%0A%20%20%20%20%2F%2F%20create(obj%3A%20DocumentType)%3A%20Promise%3CDocumentType%3E%0A%20%20%20%20%2F%2F%20create(obj%3A%20DocumentType%2C%20done%3A%20ObjectCallback%3CDocumentType%3E)%3A%20void%0A%20%20%20%20create(obj%3A%20DocumentType%2C%20done%3F%3A%20(error%3A%20Error%2C%20result%3F%3A%20DocumentType)%20%3D%3E%20void)%20%3A%20void%20%7C%20Promise%3CDocumentType%3E%20%7B%0A%20%20%20%20%20%20%20%20if%20(done)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20done(undefined%2C%20obj)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20Promise.resolve%3CDocumentType%3E(obj)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%7D%0A" rel="nofollow">http://www.typescriptlang.org/play/index.html#src=declare%20abstract%20class%20SlimDocumentDatabase%3CT%3E%20%7B%0A%20%20%20%20create(obj%3A%20T)%3A%20Promise%3CT%3E%0A%20%20%20%20create(obj%3A%20T%2C%20done%3A%20(error%3A%20Error%2C%20result%3F%3A%20T)%20%3D%3E%20void)%3A%20void%0A%7D%0A%0A%0Aclass%20SlimAdaptor%3CDocumentType%3E%20implements%20SlimDocumentDatabase%3CDocumentType%3E%20%7B%0A%20%20%20%20%2F%2F%20create(obj%3A%20DocumentType)%3A%20Promise%3CDocumentType%3E%0A%20%20%20%20%2F%2F%20create(obj%3A%20DocumentType%2C%20done%3A%20ObjectCallback%3CDocumentType%3E)%3A%20void%0A%20%20%20%20create(obj%3A%20DocumentType%2C%20done%3F%3A%20(error%3A%20Error%2C%20result%3F%3A%20DocumentType)%20%3D%3E%20void)%20%3A%20void%20%7C%20Promise%3CDocumentType%3E%20%7B%0A%20%20%20%20%20%20%20%20if%20(done)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20done(undefined%2C%20obj)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20Promise.resolve%3CDocumentType%3E(obj)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%7D%0A</a></p>