Skip to content

Instantly share code, notes, and snippets.

@martinheidegger
Last active December 28, 2018 04:40
Show Gist options
  • Save martinheidegger/715370d211cc9fbf63338fdd64396d8a to your computer and use it in GitHub Desktop.
Save martinheidegger/715370d211cc9fbf63338fdd64396d8a to your computer and use it in GitHub Desktop.
TypeScript definitions with different return types

How do I write the following JavaScript in Typescript most efficiently?

  • sample.js does a fairly simplified example for a code with the logic: "if callback, then callback, else promise" in add and a logAndAdd method reuses add, so the result of logAndAdd will also be either a callback or a promise, depending on the input.

  • test.js makes sure that this is supposed to work

  • sample.d.ts is how I assume the .d.ts should look like

  • sample.ts is not working but shows how I thought TypeScript could work neatly.

How would you write it in TypeScript?

export function add <T> (data: T): Promise<void>
export function add <T> (data: T, cb: (err: Error) => void): void
export function logAndAdd <T> (data: T): Promise<void>
export function logAndAdd <T> (data: T, cb: (err: Error) => void): void
function add (data, cb) {
if (cb) {
setTimeout(cb, 1, null, data)
return
}
const p = new Promise((resolve, reject) => {
add(data, (err, data) => err ? reject(err) : resolve(data))
})
return p
}
function logAndAdd (data, cb) {
console.log('logging', data)
return add(data, cb)
}
module.exports = {
add, logAndAdd
}
// This has multiple compile errors
export function add <T> (data: T): Promise<void>
export function add <T> (data: T, cb: (err: Error, data?: T) => void): void {
if (cb) {
setTimeout(cb, 1, null, data)
return
}
const p = new Promise<void>((resolve, reject) => {
add(data, (err: Error, data?: T) => err ? reject(err) : resolve(data))
})
return p
}
export function logAndAdd <T> (data: T, cb?: (err: Error, data?: T) => void) {
return add(data, cb)
}
const { add, logAndAdd } = require('./sample')
const assert = require('assert')
assert.equal(null,
add('x', err => {
console.log('x finished' + err)
})
)
add('y').then(() => { console.log('y finished') })
assert.equal(null,
logAndAdd('a', err => {
console.log('a finished: ' + err)
})
)
logAndAdd('b').then(() => { console.log('b finished')})
@martinheidegger
Copy link
Author

martinheidegger commented Dec 28, 2018

This is what I have come up with:

export function add (data: string): Promise<string>
export function add (data: string, cb: (err: Error, data?: string) => void): void
export function add (data: string, cb?: (err: Error, data?: string) => void): any {
  if (cb) {
    setTimeout(cb, 1, null, data)
    return
  }
  return new Promise<string>((resolve, reject) => {
    add(data, (err: Error, data?: string) => err ? reject(err) : resolve(data))
  })
}

export function logAndAdd (data: string): Promise<string>
export function logAndAdd (data: string, cb: (err: Error, data?: string) => void): void
export function logAndAdd (data: string, cb?: (err: Error, data?: string) => void): any {
  console.log('adding')
  return add(data, cb)
}

@martinheidegger
Copy link
Author

I opened this issue as consequence: microsoft/TypeScript#29182

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment