Reputation: 1148
I have the following code:
type testUnion = Array<any> | string;
class testClass {
testProp: testUnion;
}
const bar = new testClass()
bar.testProp.forEach(...) //property forEach does not exist on type testUnion
However testUnion is an array OR a string and the property for each exists on the Array class. Why is typescript not seeing it as an Array or a String. The only intelisense I get is a method 'valueOf'
any ideas?
EDIT
full code below, the loadTrait method in the Developer class is what is in question, I also included the Trait class and all the relevant interfaces just incase there are any other suggestions.
interface devInit {
locations: Array<Location>;
traits: Array<Trait>;
props: developerProp;
name: string;
}
interface developerProp {
acceptedMaritalStatuses: maritalStatusType;
ageTop: number;
ageBottom: number;
income: number;
majorCCRequired: boolean;
}
class Developer {
locations: traitLocationType;
props: developerProp;
name: string;
private traits: Array<Trait> = [];
constructor(init: devInit) {
Object.assign(this, init);
$notesApi.subscribe((_notes) => {
this.notesApi = _notes;
});
}
private notesApi: notesApiType;
//only load after traits have been loaded.
private loadExternalNotes() {
//@ts-ignore
if (_notes === '') return;
this.locations.forEach((_location) => {
const gifts = new Note(
'gifts',
this.notesApi[this.name][_location.name].gifts
);
const notes = new Note(
'gifts',
this.notesApi[this.name][_location.name].notes
);
_location.addNote(gifts);
_location.addNote(notes);
});
}
private loadTraits() {
this.traits.forEach((_trait) => {
_trait.runRules();
if (!_trait.key) return;
if (_trait.key === 'locations') {
if(Array.isArray(_trait.value))
_trait.value.forEach((_traitValue) => {
this.locations.push(_traitValue);
});
}
});
}
}
class Trait {
constructor(traitKey: traitKeyType, traitValue: traitValueType) {
this._key = traitKey;
this._value = traitValue;
}
private _key: traitKeyType;
private _value: Array<any> | string;
private status = false;
private notes: Array<Note> = [];
private rules: Array<Rule> = [];
get key() {
if (!this.status) return null;
return this._key;
}
get value() {
if (!this.status) return null;
return this._value;
}
addRule(rule: Rule) {
this.rules.push(rule);
return this;
}
runRules() {
const getInfoFromRules = (_rule: Rule) => {
_rule.run();
this.notes.push(_rule.note);
return _rule.status;
};
this.status = this.rules.map(getInfoFromRules).indexOf(false) === -1;
}
}
type traitValueType = Array<any> | string;
// | maritalStatusType
// | traitLocationType
// | traitLocationType
// | boolean;
type maritalStatusType = 'married' | 'coHab' | 'singleMale' | 'singleFemale'[];
type traitLocationType = Array<Location>;
Upvotes: 0
Views: 41
Reputation: 29325
because it can be an array OR a string. TS doesn't know which it is, you have to tell it...
you can use a type check:
if (Array.isArray(bar.testProp)) {
bar.testProp.forEach(...) // this is fine
}
or if you KNOW it's in fact an array, you can use a type assertion:
(bar.testProp as Array<any>).forEach(...) // also fine
Upvotes: 2