Issue
I have two classes and a service storing data in a map with a string key to access, stored data is of type of one of these 2 classes.
class DummyObj {
constructor(public text: string, public dummy: string){}
}
class DummySecondObj {
constructor(public text: string, public dummySecond: number){}
}
type ValidTypes = DummyObj | DummySecondObj | undefined;
class ServiceClass {
private readonly storage = new Map<string, ValidTypes>();
constructor() {
this.storage.set('key1', { text: 'dummy 1', dummy: 'dummy element 1' });
this.storage.set('key2', { text: 'dummy 2', dummySecond: 4 });
this.storage.set('key3', new DummyObj('dummy 1','dummy element 1'));
this.storage.set('key4', new DummySecondObj('dummy 1', 4));
}
getData(resourceKey: string): ValidTypes {
if (this.storage.has(resourceKey)) {
const meta = this.storage.get(resourceKey);
//console.log(meta);
if (meta instanceof DummyObj) {
console.log('is DummyObj');
return (this.storage.get(resourceKey) as DummyObj);
}
else if (meta instanceof DummySecondObj) {
console.log('is DummySecondObj');
return (this.storage.get(resourceKey) as DummySecondObj);
}
else {
console.log('not found')
return undefined
}
}
return undefined;
}
}
When called the method getData I would expect that instanceof is able to see the structure equal to my class and return with the correct state but this is not true if not created with the constructor but just as inline object. There is a way to make it work also with the inline generic object initialization? And can someone point me out why exactly is it not working? thank you
const service = new ServiceClass();
var x = service.getData('key1');
var x = service.getData('key2');
var x = service.getData('key3');
var x = service.getData('key4');
Here also the running example live example
[Updated]
Solution
It is not working because your object simply is not an instance of any of the classes you defined. Your right that they happen to have the same properties, but it isn't of the same type.
Consider two classes
class Person {
constructor(public name: string) {}
}
class Animal{
constructor(public name: string) {}
}
both classes have a property called name
. However, an instance of one class can never be an instance of the other.
Imagine this would work:
new Animal("simba") instanceof Person // imagine this is true
That would be absurd.
In the same way, creating an object inline does not make it an instance of any other class you defined, just because the properties are the same. Inline created objects are an instance of Object
.
What you want is to convert the meta data from the storage to an actual instance of your class. There is no default way to do this in javascript. But a simple example could be:
class DummyObj {
constructor(public text: string, public dummy: string){}
static isValidMetadata(data: any) {
return data.hasOwnProperty('text') && data.hasOwnProperty('dummy');
}
}
class DummySecondObj {
constructor(public text: string, public dummySecond: number){}
static isValidMetadata(data: any) {
return data.hasOwnProperty('text') && data.hasOwnProperty('dummySecond');
}
}
class ServiceClass {
private readonly storage = new Map<string, ValidTypes>();
constructor() {
this.storage.set('key1', { text: 'dummy 1', dummy: 'dummy element 1' });
this.storage.set('key2', { text: 'dummy 2', dummySecond: 4 });
this.storage.set('key3', new DummyObj('dummy 1','dummy element 1'));
this.storage.set('key4', new DummySecondObj('dummy 1', 4));
}
getData(resourceKey: string): ValidTypes {
if (this.storage.has(resourceKey)) {
const meta = this.storage.get(resourceKey);
//console.log(meta);
if (DummyObj.isValidMetadata(meta)) {
console.log('is DummyObj');
return (new DummyObj(meta.text, meta.dummy));
}
else if (DummySecondObj.isValidMetadata(meta)) {
console.log('is DummySecondObj');
return (new DummySecondObj(meta.text, meta.dummySecond));
}
else {
console.log('not found')
return undefined
}
}
return undefined;
}
}
Notice the code does two things:
- validate that the data from storage has the correct properties
- Convert the meta data to an actual instance of the class
Answered By - yadejo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.