Bridge Training

Types

Every type and value exported from @workspace/bridge/types, grouped by source file.

Import from @workspace/bridge/types. The sub-path is type-only except for three runtime values: PLAY_CONTEXT_INFOS, EMPTY_PAR_DATA and EMPTY_PAR_HINT.

types.ts
const declarer: Player = "S";
const card: Card = "SA";
const contract: Contract = new ContractBuilder().fromCompact("4H").build();
// => { level: 4, suit: "H", trump: "H", declarer: "S", doubled: "none" }

Player

TypeValuesDescription
Player"N" | "E" | "S" | "W"Seat at the table, derived from the PLAYER constant.
Partnership"NS" | "EW"Two players sitting opposite each other.
PartnershipRecord<T>Record<Partnership, T>Map keyed by partnership.
PlayerSide"attack" | "defense"Declaring or defending side.
ValidPlayerCount2 | 4Seats taking part: all four, or only North and South (determineOpener).

Hands

TypeDefinitionDescription
Suit"S" | "H" | "D" | "C"Card suit.
Rank"A" | "K" | "Q" | "J" | "T" | "9" … "2"Card rank, T is ten.
Card${Suit}${Rank}Suit followed by rank: "SA", "H7", "DT". The canonical form, stored and returned everywhere.
CardPartsReadonly<{ suit: Suit; rank: Rank }>A card as its two fields. Import from @workspace/bridge/card.
CardInputCard | CardPartsWhat card-taking functions accept; toCard normalises it. Import from @workspace/bridge/card.
HandData<TCard extends string = string>Record<Suit, TCard[]>Generic hand, any string card representation.
HandsData<TCard extends string = string>Record<Player, HandData<TCard>>Generic four-hand record.

A hand of full cards is HandData<Card>, four of them HandsData<Card>. The stored rank-string hands, Hand and Hands, are under Deal.

Bid

TypeDefinitionDescription
BidLevel1 | 2 | 3 | 4 | 5 | 6 | 7Tricks above the book of six.
DenominationSuit | "NT"Biddable strain.
SpecialBid"Pass" | "X" | "XX" | "Alert"Non-regular calls.
RegularBid${BidLevel}${Denomination}"1H", "3NT", "7S".
BidRegularBid | SpecialBidAny call. The canonical form, stored and returned everywhere.
RegularBidParts{ level: BidLevel; suit: Denomination }A regular bid as its two fields; splitBid reads it, toBid writes it.
BidInputBid | RegularBidPartsWhat bid-taking functions accept. Import from @workspace/bridge/auction.
CounterStatus"none" | "X" | "XX"Double or redouble status.
BidCompositeRegularBidComposite | SpecialBidCompositeA call with its auction context.

RegularBidComposite

Prop

Type

SpecialBidComposite

Prop

Type

Contract

The final contract after the auction. trump is derivable from suit and may be omitted.

Prop

Type

ContractResult

Prop

Type

DisplayContract

A contract without declarer, for strings such as "3NT" or "4SX".

Prop

Type

Contract

ContractLevel classifies a contract: "partial" | "game" | "small_slam" | "grand_slam".

Auction

The auction is stored and passed around as an Auction (see Deal and Canonical forms). BidInfo is the per-call view auctionEntries derives from it: the seat and position come from the dealer and the call's index, they are never stored.

BidInfo

Generic over TComment (defaults to unknown).

Prop

Type

types.ts
const auction: Auction = new AuctionBuilder().fromCompact("N / 1H pass 2H AP").build();
const entries: BidInfo[] = auctionEntries(auction);
entries[0]; // { bid: "1H", player: "N", position: 0 }

AuctionBidCell

One cell of an auction display. Same content as BidInfo with the position named index; auctionMovesToBidCells (Format) builds it.

Prop

Type

Deal

The storage shape of a deal. Hands use rank strings per suit ("AKQ2"), not Card[].

TypeDefinitionDescription
HandRecord<Suit, string>Rank string per suit, "AKQ2".
HandsRecord<Player, Hand>Four hands in rank-string format.
WithComment<T, TComment>T & { comment?: TComment }Adds an optional comment.
AuctionMove<TComment>WithComment<{ bid: Bid; isAlerted?: boolean }, TComment>One call in a stored auction.
PlayMove<TComment>WithComment<{ card: Card }, TComment>One card in a stored play.
Auction<TComment>Sequence<AuctionMove<TComment>>Calls clockwise from first (the dealer).
Play<TComment>Sequence<PlayMove<TComment>>Cards in chronological order from first (the opening leader).

Sequence

Prop

Type

DealMetadata

result is stored verbatim: a trick count, a RESULT_EXPECTED sentinel, or "" as a transient marker.

Prop

Type

Deal

Generic over TAuctionComment, TPlayComment and TReview, all defaulting to unknown.

Prop

Type

types.ts
const deal: Deal = makeDeal({ contract, player: declarer });
deal.cards.N.S; // rank string, e.g. "AKQ2"
deal.auction.first; // dealer
deal.play.moves; // chronological PlayMove[]

Play

PlayEntry

Prop

Type

Trick

Prop

Type

PlayAnnotation

Prop

Type

Canonical forms

Scalars have one canonical form and one input union: Card / CardInput and Bid / BidInput, normalised by toCard and toBid at the public boundary (Card, Auction). Aggregates do not get an input union: a union on a hand, auction or trick shape costs a discriminant on every call, degrades inference and is ambiguous at runtime (an array of strings may hold cards or ranks).

Each aggregate has instead one stored form, named without a Deal prefix. Data that can be derived from it, such as a call's seat and position or a trick's winner, lives in a view that a named function produces. A view is never stored, and never passed around as a second canonical form.

ConceptTypeRole
Stored hands, a rank string per suitHand / HandsDeal.cards, PBN, LIN, database.
Hands in memory, an array per suitHandData<T> / HandsData<T>Every function of @workspace/bridge/hands, @workspace/bridge/play, engine.hands and engine.play. HandsData<Card> holds full cards.
Stored playPlay + PlayMoveDeal.play, chronological from the opening leader.
TricksTrick + PlayEntryView built by buildTricks / buildTricksFromDeal, which derive seats and winners while walking the play. Form data parses into it through trickSchema.
Stored auctionAuction + AuctionMoveDeal.auction. Every auction rule takes and returns it.
Calls with their seatBidInfoView built by auctionEntries: seat and position come from the dealer and the call's index.
Auction display cellAuctionBidCellView built by auctionMovesToBidCells for ui-bridge auction tables.

Crossing points:

  • Hands: handsToHandsData and handsDataToHands (@workspace/bridge/hands).
  • Play: buildTricks turns a Play into Trick[]; PlayMoveLike ({ card: string }) is the minimal move shape it and engine.play.validateTricks accept.
  • Auction: auctionEntries turns an Auction into BidInfo[]; nothing turns a view back into the stored form.
  • Legacy input: the per-seat auction arrays ({ first, N, E, S, W }) still served by the legacy deal endpoint are parsed into an Auction where the player maps its DTO. Rows read straight from the database go through deriveContractResultFromAuction and deriveFinalDeclarerFromAuction, which accept unbranded bid strings.

createRandomAuction from @workspace/bridge/testing and createBoardGame from @workspace/bridge/factories both return an Auction.

Config

TypeDefinitionDescription
AuctionMode"trump" | "goal" | "contract" | "sequence" | "interactive"How the auction behaves in a mode.
SuitVariant"classic" | "petit-bridge"Suit set and display rules.
HonorMetric"hcp" | "tht"Partner-hand pill unit: High Card Points or Total Top-Honor-Tricks.
PlayContextInfo"lead" | "trump" | "objective" | "contract" | "scoring" | "sequence"One deal fact exposed during play.
SuitDistributionReadonly<Record<Suit, number>>Initial suit lengths of a hand.
ImposedSuitOrderreadonly Suit[] | ((ctx: SuitOrderContext) => readonly Suit[])Fixed or context-derived reading order.

SuitOrderContext

Prop

Type

CoreConfig

Game rules for a teaching mode. Resolved from the mode inside the engine and exposed as engine.hands.config; not meant to be assembled by hand.

Prop

Type

PLAY_CONTEXT_INFOS

Runtime tuple of every PlayContextInfo, in canonical order.

types.ts
const infos: readonly PlayContextInfo[] = PLAY_CONTEXT_INFOS;
// => ["lead", "trump", "objective", "contract", "scoring", "sequence"]
const hint: ParHint = { ...EMPTY_PAR_HINT, loading: true };

Par

ParData is what a synchronous solver returns. ParHint adds the async flags and the residual trick count. NSParHint expresses the bound in the NS frame for reachability checks.

ParData

Prop

Type

ParHint

Prop

Type

NSParHint

Prop

Type

ValueDescription
EMPTY_PAR_DATAParData with every field null.
EMPTY_PAR_HINTParHint with no data, loading: false, error: null.

PBN

Types for the Portable Bridge Notation parser. PBNPlay is the wire format in column order per seat, not chronological order.

TypeDefinitionDescription
PBN<TPlayer>${TPlayer}:${hand} ${hand} ${hand} ${hand}Inline deal string, "N:AKQ.JT.9876.5432 …".
PBNVulnerabilityValue"None" | "NS" | "EW" | "All"PBN tag spelling.
PBNScoringValue"IMP" | "TPP"PBN tag spelling.
PBNTeachingValuethe 12 teaching modesValues of the PBN_TEACHING tuple.
PBNNoteTarget"play" | "auction"Which section a note belongs to.

PBNCard

Prop

Type

PBNParseData

Prop

Type

PBNNote

Prop

Type

PBNNotes

Prop

Type

PBNAuction

Prop

Type

PBNPlay

Prop

Type

PBNDeal

Prop

Type

ParserState

Prop

Type

Scoring

TypeValues
ScoringMode"UNSET" | "TPP" | "IMP"
ScoringModeUnset"UNSET"
ScoringModeSet"TPP" | "IMP"

TeachingMode

TeachingMode is the union of the 12 modes a deal can be in: "auction", "show-trump-goal", "no-auction", "show-trump", "show-contract", "h", "hd", "hld", "tht", "sequence", "petit-bridge", "no-dummy". See Game Modes for what each one enables.

Vulnerability

TypeValuesDescription
Vulnerability"UNSET" | "NONE" | "NS" | "EW" | "ALL"Deal-level setting.
VulnerabilityStatus"vulnerable" | "non-vulnerable" | "unset"Resolved for one player.

Locale

Locale is the union of the LOCALES tuple from @workspace/bridge/constants: "en" | "fr" | "es" | "it" | "ca" | "de" | "pt" | "el" | "nl" | "sv" | "pl".

Analysis

TypeDefinitionDescription
SuitCountRecord<Suit, number>Cards per suit in one hand.
DealAnalysisRecord<Player, HandAnalysis>Analysis of all four hands.

HandAnalysis

Prop

Type

Notation and PBN helpers

These types belong to other modules and are imported from them: RankMapping and RankFormatter from @workspace/bridge/notation, DealCommentSummary from @workspace/bridge/pbn.

TypeDefinitionDescription
RankMappingPartial<Record<Rank, readonly string[]>>Standard rank to accepted inputs; the first entry is the display form.
RankFormatter(rank: Rank) => string | nullInternal rank to display string.

DealCommentSummary

Returned by engine.pbn.detectDealComments and engine.pbn.detectDealsComments.

Prop

Type