Typescript weirdness: function vs. => and "this"
Alright, I ran into a non-obvious problem with Typescript and want to share. I guess it can also be chalked up to “Javascript weirdness” but the second layer of Typescript confused me.
I have basketball games and I want to create a quick dictionary of a team to all of their games. I wrote code like this:
class Season { teamsToGames: { [teamName: string]: Array; } = {}; addGame(g : Game) { .map([game.homeTeam, game.awayTeam], function(teamname) { if(!.has(this.teamsToGames, teamname)) { this.teamsToGames[teamname] = [] } this.teamsToGames[teamname].push(game) }) } }
Simple, right? Take the home team and away team in a quick map function and do the reverse mapping to the game. But I kept getting this error (Xavier is one of the schools in the game data):
test.js:15 this.teamsToGames[teamname] = [];
TypeError: Cannot set property ‘‘Xavier’’ of undefined at test.js:15:45 at Function..map..collect (underscore.js:124:24) at Season.addGame (test.js:12:11) at Transform. (test.js:73:20) at Transform.emit (events.js:92:17) at emitReadable_ (_stream_readable.js:426:10) at emitReadable (_stream_readable.js:422:5) at readableAddChunk (_stream_readable.js:165:9) at Transform.Readable.push (_stream_readable.js:127:10) at Transform.push (_stream_transform.js:140:32)
I couldn’t figure it out. Was I not initializing the map correctly? Did class syntax somehow mean something different?
No, the problem is the function I’m using in that simple _.map portion. Typescript requires you to use => syntax for anonymous functions that capture the “this” keyword in a class. So if you’re initializing a class instance variable and find that variable “undefined” when you try to use it, this is what’s happening. Change your function () { } declarations to () => { }. So the new code is:
class Season { teamsToGames: { [teamName: string]: Array; } = {}; addGame(g : Game) { .map([game.homeTeam, game.awayTeam], (teamname) => { if(!.has(this.teamsToGames, teamname)) { this.teamsToGames[teamname] = [] } this.teamsToGames[teamname].push(game) }) } }