Promise Combinator Shape
Promise.any value fidelity and Promise.allSettled result shape.
Two combinator details that must match Node/JS exactly:
1. Promise.any resolves to the first *fulfilled* member's value, skipping rejected ones — including when the rejected member comes first and the fulfilled winner is a number (its value must not be mis-decoded). 2. Promise.allSettled reports each member as either { status: "fulfilled", value } or { status: "rejected", reason } — only the applicable key, and the raw rejection value as `reason`.
// ── Promise.any: reject-first, numeric winner ───────────────────────────────
async function firstNumber(): Promise<number> {
return await Promise.any([Promise.reject("skipped"), Promise.resolve(2)])
}
firstNumber().then((v) => {
console.log(v) // 2
})
// ── Promise.any: reject-first, string winner ────────────────────────────────
async function firstString(): Promise<string> {
return await Promise.any([Promise.reject("skipped"), Promise.resolve("hi")])
}
firstString().then((v) => {
console.log(v) // hi
})
// ── Promise.allSettled: per-element shape via JSON ──────────────────────────
async function settledShape(): Promise<string> {
return JSON.stringify(
await Promise.allSettled([Promise.resolve(1), Promise.reject("e")]),
)
}
settledShape().then((v) => {
// [{"status":"fulfilled","value":1},{"status":"rejected","reason":"e"}]
console.log(v)
})
// ── Promise.allSettled: direct property access ──────────────────────────────
const results = await Promise.allSettled([
Promise.resolve(7),
Promise.reject("boom"),
])
console.log(results[0].status) // fulfilled
console.log(results[0].value) // 7
console.log(results[1].status) // rejected
// ── Promise.allSettled: rejection reason keeps its original value ────────────
// `reason` is the original rejected value, not a coerced Error: a number stays
// a number (typeof + JSON), and a rejected Error is recovered at every site —
// `reason.message`/`.name`, String(reason), JSON `{}`, and `instanceof Error`.
const mixed = await Promise.allSettled([
Promise.reject(42),
Promise.reject(new TypeError("bad input")),
])
const numReason = mixed[0]
if (numReason.status === "rejected") {
console.log(typeof numReason.reason, numReason.reason) // number 42
}
const errReason = mixed[1]
if (errReason.status === "rejected") {
const r = errReason.reason
console.log(r.message, r.name) // bad input TypeError
console.log(String(r)) // TypeError: bad input
console.log(r instanceof Error) // true
console.log(r instanceof TypeError) // true
}
console.log(JSON.stringify(mixed))
// [{"status":"rejected","reason":42},{"status":"rejected","reason":{}}]View source on GitHubexamples/async/promise_combinator_shape.ts