I wonder if a good distinction is user initiated actions versus system initiated. If the user begins the action, the changes are immediate and buffered to the interface that appears next.
But when the system initiates it (eg. notifications, popups), then the prior interface remains active.
There's this paper studying this, and I think more work on it too.. https://dl.acm.org/doi/full/10.1145/3660338
The ceremony is caused not by typescript but your misuse of map. You don’t need to create perserverid as an object first. Instead you could flatten fe.blocks, and then filter by b.serverId and then map to a key,value array and use Object.fromEntries to turn this into a keyed object.
Something like:
const perServerId = Object.fromEntries(uploaderFiles.flatMap(fe => fe.blocks).filter(b => Boolean(b.serverId)).map(b => [b.serverId,b]))
And typescript infers the types correctly. But I still wouldn’t write it as one line, and I’d use lodash instead.