Created
November 9, 2022 02:05
-
-
Save cefn/73f26fb02034165edf584ddbedcc39a4 to your computer and use it in GitHub Desktop.
Interactive Story sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Passage = string; | |
async function tell(passage: Passage): Promise<void> {} | |
async function choose<Choice extends string>( | |
passage: Passage, | |
choices: Record<Choice, Passage> | |
): Promise<Choice> { | |
return Object.keys(choices)[0] as Choice; | |
} | |
type AsyncFn = (...args: any[]) => Promise<any>; | |
interface Call<Fn extends AsyncFn> { | |
kind: "call"; | |
fn: Fn; | |
args: Parameters<Fn>; | |
} | |
function* call<Fn extends AsyncFn>( | |
fn: Fn, | |
args: Parameters<Fn> | |
): Generator<Call<Fn>, Awaited<ReturnType<Fn>>, Awaited<ReturnType<Fn>>> { | |
return yield { | |
kind: "call", | |
fn, | |
args, | |
}; | |
} | |
type CallStack<Fn extends AsyncFn, Ret> = () => Generator< | |
Call<Fn>, | |
Ret, | |
Awaited<ReturnType<Fn>> | |
>; | |
type StoryFn = typeof tell | typeof choose; | |
let roomId: RoomId = "lobby"; | |
const story: CallStack<StoryFn, void> = function* () { | |
for (;;) { | |
const room = ROOMS[roomId]; | |
roomId = yield* room(); | |
} | |
}; | |
const ROOMIDS = ["lobby", "bar", "cloakroom"] as const; | |
type RoomId = typeof ROOMIDS[number]; | |
type Room = CallStack<StoryFn, RoomId>; | |
const lobby: Room = function* () { | |
yield* call(tell, ["hello"]); | |
return "bar"; | |
}; | |
const bar: Room = function* () { | |
yield* call(tell, ["hello"]); | |
return "cloakroom"; | |
}; | |
const cloakroom: Room = function* () { | |
yield* call(tell, ["hello"]); | |
return "lobby"; | |
}; | |
const ROOMS: Record<RoomId, Room> = { | |
lobby, | |
bar, | |
cloakroom, | |
} as const; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment