I am a noob in working with typescript, but cannot avoid it in angular. So, I was writing the code as I learn.
I wanted to make a function that iterates over the keys of an object and performs some small tasks. In my case, I want to iterate through the keys because interface properties are optional and all of them may not be present. Here is the relevant part of my code: -
interface GameState {
gameId?: string,
minPlayers?: number,
currentChoiceMakingPlayer?: number,
gameEndReason?: string,
}
export class GameManagerService {
gameState: GameState = {};
synchroniseGameData = (gameState: GameState) => {
for (let key in Object.keys(gameState)) {
let typeKey = <keyof GameState>key;
this.updateEntryInGameState(typeKey, gameState[typeKey]);
}
};
updateEntryInGameState = <GameStateKey extends keyof GameState>(key: GameStateKey, value: GameState[GameStateKey]) => {
this.gameState[key] = value;
};
}
I understand most of it, except for the actual spotlight stealer function updateEntryInGameState
(bottom of the code).
The tutorial I used gave this brief explanation (which I'll translate with respect to parameter names in my code): -
Adding the type variable
GameStateKey
for thekey
type allows us to use it for thevalue
type while still ensuring that thekey
is a key of GameState usingextends keyof GameState
But I still don't fully understand how this works.
Mainly, What does <GameStateKey extends keyof GameState>
do before the function definition? And how is it being applied to the parameters of the function?
CodePudding user response:
What does
<GameStateKey extends keyof GameState>
do before the function definition?
It defines a generic type parameter for the arrow function being assigned to updateEntryInGameState
.
And how is it being applied to the parameters of the function?
Wherever you see GameStateKey
in the rest of the function's code, it gets its type from the type parameter. When you call updateEntryInGameState
, the type of GameStateKey
is inferred from the type of the first argument you give the function (the one received as the key
parameter), and the second argument's type is then defined as the type of the property that that key designates in a GameState
object (or subtype of it). (You can also specify the type explicitly as a type argument on the call, this.updateGameState<theTypeGoesHere>(/*...*/)
, but in this case there's no need.)
Basically, it lets you say that the key will be a key of GameState
, and the value will be of the type of the property with that key in GameState
. So during the call, if key
is "gameId"
, the type of value
will be string
; if the key
is "minPlayers"
, the type of value
will be number
.