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>) { // @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) { 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; 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;