Within my TypeScript program, I have defined two base types (Player
, State
) and a few nested Record
types that serve as mappings.
Using a typed function, an instance of one of these records is created based on an existing instance of the nested record.
type Player = "1" | "2";
type State = "A" | "B" | "C";
type StateMapping = Record<State, State>;
type PlayerStateMappings = Record<Player, StateMapping>
type PlayerStates = Record<Player, State>;
const playerStateMappings: PlayerStateMappings = {
"1": {
"A": "B",
"B": "C",
"C": "A"
},
"2": {
"C": "B",
"B": "A",
"A": "C"
},
}
function nextStates(currentState: State): PlayerStates {
var nextStates = {};
for(const player of Object.keys(playerStateMappings)){
nextStates[player] = playerStateMappings[player][currentState]
}
return nextStates;
}
console.log(nextStates("A"))
An issue arises with this code where a type error occurs at the return statement because the object was initially created without the required keys and added later:
TS2739: Type '{}' is missing the following properties from type 'PlayerStates': 1, 2
.
I am seeking a solution to avoid this type error by meeting the following criteria:
- The typesystem must remain strict, ensuring the
nextStates
function returns a complete and validPlayerStates
object. - The
nextStates
object should be generated programmatically based on the keys of theplayerStatesMapping
object, eliminating the need to hardcode all players again.
Several potential solutions found on SO either compromise condition 1 or 2:
Approaches violating condition 1:
- Making the PlayerStates type partial:
type PlayerStates = Partial<Record<Player, State>>;
- Enforcing type using the
as
keyword:
; (from this question)var nextStates = {} as PlayerStates
Approaches violating condition 2:
- Setting default values for each Player in the object creation:
var nextStates = {"1": "A", "2": "B"}
Although the typing may seem excessive in this simplified example, it accurately reflects more complex projects where the mentioned requirements are crucial.
PS: With a background in Python, I am looking for a functionality similar to dict comprehension that would facilitate initializing a new dictionary based on iteration.