Promises make time and outside work composable in TypeScript. Musi uses effects to name the outside request first, then lets handlers or runtime code decide how it runs.
const nativeClockMs = native.bind("clock_ms");foreign "c" (
let clock_ms () : Int;
);
export let nativeClockMs () : Int := unsafe {
clock_ms();
};Reading Promises, Async, and I/O Boundaries from JavaScript/TypeScript
On the Musi side, Musi names outside work with effects and request, instead of hiding time, files, console work, or services inside an ordinary-looking call. Read the shared example through JavaScript/TypeScript eyes: keep the useful instinct, then let Musi name shape, behavior, absence, and outside work in separate places.
False friend
Do not make an effect look pure. A clock, process, network service, or console changes the trust boundary. For a TypeScript reader, the trap is assuming runtime object shape and compile-time behavior contract are the same thing; Musi class is not a JS constructor or TS class; it is a behavior contract implemented separately from record/data shape.
When this pays off
Use effects when the program asks the runtime, OS, user, or another service for an answer. The JavaScript/TypeScript instinct still helps here: Keep the TypeScript habit of reading the shape before reading implementation details.