Reputation: 83
I'm trying to create a map structure to fill it dynamically with information from different sources:
export class VideoDataMap {
[videoId: string]: {
url: string,
name: string
};
}
The problem is that when i assign data to the object attributes, it says the object is undefined. If I assign a string and not the object, it works. Anyone knows what i am missing here?
public videoDataMap = new VideoDataMap();
This does not throw an error (but we are not using the object attributes)
this.videoDataMap[videoId] = url;
This throws an error
this.videoDataMap[videoId].url = url;
error: TypeError: Cannot set property 'url' of undefined
Thank you very much Best regards
Upvotes: 0
Views: 5828
Reputation: 821
I think the confusion comes because you've defined a Typescript class with structure, but not real fields. That is, the after constructed, you'll get a Javascript empty object, which makes complete sense as initially it's a map with no keys set.
It's easy to see looking into the transpiled code (for example using http://www.typescriptlang.org/play/)
Typescript:
export class VideoDataMap {
[videoId: string]: {
url: string,
name: string
};
}
Generated Javascript:
var VideoDataMap = (function () {
function VideoDataMap() {
}
return VideoDataMap;
}());
exports.VideoDataMap = VideoDataMap;
Which means, when you do:
let videoDataMap = new VideoDataMap();
You'll get something similar to:
var videoDataMap = {}
And hence when you do videoDataMap["myVideoId1"].anyProp
, you'll get the TypeError
because videoDataMap["myVideoId1"]
hasn't been initialized.
An alternative would be defining it like:
class VideoDataItem{
public url: string;
public name: string;
constructor(u: string, n: string){
this.url = u;
this.name = n;
}
}
class VideoDataMap {
[videoId: string]: VideoDataItem;
}
And using it like in the following running example: https://glot.io/snippets/ervh3vtbg9
I hope it helps.
Upvotes: 1
Reputation: 3771
How 'bout this
if (this.videoDataMap[videoId]) // check if there's an object
this.videoDataMap[videoId]["url"] = url; // only assign this field
else // is unassigned
this.videoDataMap[videoId] = {url : url}; // initialize new object
Upvotes: 2