declare const pstr: Promise<string>;
declare const pnum: Promise<number>;

Promise.all([
  pstr,
  pnum,
  true, // non-Promise values passed through
]).then((xs) => {
  // tuple information is preserved
  let [a,b,c] = xs;
  a as number;  // Error: string ~> number
  b as boolean; // Error: number ~> boolean
  c as string;  // Error: boolean ~> string

  // array element type is (string | number | boolean)
  xs.forEach(x => {
    x as void;  // Errors: string ~> void, number ~> void, boolean ~> void
  });
});

// First argument is required
Promise.all<Array<unknown>>(); // Error: expected array instead of undefined (too few arguments)

// Mis-typed arg
Promise.all<Array<unknown>>(0); // Error: expected array instead of number

// Promise.all supports iterables
function test(val: Iterable<Promise<number>>) {
  const r: Promise<ReadonlyArray<number>> = Promise.all(val);
}

function test2(val: Map<string, Promise<number>>) {
  const r: Promise<ReadonlyArray<number>> = Promise.all(val.values());
}

function test3(val: Array<Promise<number>>) {
  const r: Promise<Array<number>> = Promise.all(val);
}
