You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
36 lines
1.3 KiB
36 lines
1.3 KiB
import type {
|
|
ActionHandler,
|
|
DeepReadonly,
|
|
GameDefinition,
|
|
Position,
|
|
} from './contracts.ts';
|
|
|
|
type Config = { columns: number };
|
|
type Data = { grid: number[] };
|
|
type View = { grid: number[] };
|
|
type Drop = { type: 'drop'; payload: { column: number } };
|
|
type Event = { type: 'disc.dropped'; payload: { row: number; column: number } };
|
|
|
|
function readonlyContract(position: DeepReadonly<Position<Config, Data>>) {
|
|
// @ts-expect-error Nested arrays must be immutable at the module boundary.
|
|
position.data.grid.push(1);
|
|
// @ts-expect-error Nested configuration must also be immutable.
|
|
position.config.columns = 9;
|
|
}
|
|
function actionContract(handler: ActionHandler<Config, Data, Drop, Event>) {
|
|
handler.schema.parse({ type: 'drop', payload: { column: 3 } });
|
|
// @ts-expect-error apply is synchronous; a Promise is not a rule transition.
|
|
handler.apply = async () => ({ ok: true });
|
|
}
|
|
type Definition = GameDefinition<Config, Data, View, Drop, Event, Event>;
|
|
function definitionContract(definition: Definition) {
|
|
// @ts-expect-error Only declared action discriminants can be registered.
|
|
definition.actions.fire;
|
|
// @ts-expect-error The canonical action payload is checked by TypeScript.
|
|
const invalid: Drop = { type: 'drop', payload: { cell: 1 } };
|
|
return invalid;
|
|
}
|
|
void readonlyContract;
|
|
void actionContract;
|
|
void definitionContract;
|