You could use Array.reduce.
//type: [number]
var myArray = [1, 2, 3, 4, 5, 6] //doesn't really matter
//type: number -> Promise<number>
function myPromise(num){
  return new Promise((resolve) => {
    window.setTimeout(()=>{
      resolve(console.log("done: " + num)  )
    },2000)
  })
}
//Array.reduce has type: [a] ~> ((b, a) -> b), b) -> b
//So it can have type:
//[number] ~> ((Promise<number>, number) -> Promise<number>), Promise<number>) -> Promise<number>
//Therefore we need to give reduce a function that takes a Promise 
//resolving to a number and a number which makes a new promise.
//This is the function we want:
function sequencePromises(promise, number) {
  return new Promise((resolve) => {
    resolve(promise.then(_ => myPromise(number)));
  });
} 
myArray.reduce(sequencePromises, Promise.resolve());
Of course, this simplistic approach won't work if you have a promise which can error, or if you need previous results, so you might want to make sequencePromises more generic:
function genericSequencePromises(promiseFunction) {
  return (promise, parameter) => {
    return new Promise((resolve, reject) => 
                         return promiseFunction(resolve, 
                                                reject, 
                                                promise, 
                                                parameter));
  }
}
Then you can do whatever you want as long as you return a Promise.
Finally, you might benefit from this little helper:
function promiseSeries(array, reducer) {
  return array.reduce(reducer, Promise.resolve());
}
Bringing it all together:
let sequencePromises = genericSequencePromises((resolve, reject, promise, num) => {
  resolve(promise.then(_ => console.log(`done: ${num}`)));
}
promiseSeries(myArray, sequencePromises);
This way, you can not only handle the case in your question, but much more complex cases.