I have defined two types, Team
and Position
. They are both part of an array that I iterate over in my react ponent.
based on the types defined below in my map
function I am seeing the following error.
Examples of errors I am seeing.
Property 'name' does not exist on type 'Position'. [2339]
Property 'position' does not exist on type 'Team'. [2339]
Is it not possible to check that the array contains either type?
My code looks like as follows:
type Team = {
name: string;
city: string;
}
type Position = {
position: number;
}
const Component = () => {
const teamsAndPosition = [
{
name: 'Arsenal',
city: 'London',
},
{
name: 'Everton',
city: 'Liverpool',
},
{
position: 2
}
];
const [list, setList] = useState<Array<Team | Position >>(teams)
list.map((item: Team | Position) => {
return item.name ? (
<div>
// I am seeing an error for these below
<p>{item.name}</p>
<p>{item.city}</p>
</div>
) : (
<p>{item.position}</p>
)
})
}
I have defined two types, Team
and Position
. They are both part of an array that I iterate over in my react ponent.
based on the types defined below in my map
function I am seeing the following error.
Examples of errors I am seeing.
Property 'name' does not exist on type 'Position'. [2339]
Property 'position' does not exist on type 'Team'. [2339]
Is it not possible to check that the array contains either type?
My code looks like as follows:
type Team = {
name: string;
city: string;
}
type Position = {
position: number;
}
const Component = () => {
const teamsAndPosition = [
{
name: 'Arsenal',
city: 'London',
},
{
name: 'Everton',
city: 'Liverpool',
},
{
position: 2
}
];
const [list, setList] = useState<Array<Team | Position >>(teams)
list.map((item: Team | Position) => {
return item.name ? (
<div>
// I am seeing an error for these below
<p>{item.name}</p>
<p>{item.city}</p>
</div>
) : (
<p>{item.position}</p>
)
})
}
Share
Improve this question
edited Jun 20, 2020 at 9:12
CommunityBot
11 silver badge
asked Jan 25, 2019 at 16:36
peter flanaganpeter flanagan
9,85027 gold badges82 silver badges140 bronze badges
7
-
2
well if
item
can beTeam
orPosition
should you show theitem.name
anditem.position
alternatively, depding of the type ofitem
? – Titian Cernicova-Dragomir Commented Jan 25, 2019 at 16:39 - it is a bit more plicated than what I have posted here. I have dumbed down the example here for the question. Hopefully it still makes sense :-D. Basically I show a different element/ponent based on the object passed in. but the array can contain either our. Blame the designers :-) – peter flanagan Commented Jan 25, 2019 at 16:40
-
In both cases, you face a scenario, where property does not exist. You may want to extend your types with
?
optional property, or do a{item.name ? item.name : ''}
– Shevchenko Viktor Commented Jan 25, 2019 at 16:44 - @TitianCernicova-Dragomir has a good working solution for you. Alternately, if you have the option to change some things around, you could consider making both Team and Position members of a parent class and then call the properties canonically so that there are no requests that can't be fulfilled. Still, I would add checks to make sure properties are available before trying to access them, else you will run the risk of errors whenever data is inplete. – J E Carter II Commented Jan 25, 2019 at 16:54
- hmmm, obviously I appreciate the help, but I am not sure I really like either of these solutions. The array will always contain one. I will update the question with the array included. – peter flanagan Commented Jan 25, 2019 at 16:57
1 Answer
Reset to default 5When dealing with a variable that might be one of two (or more) types you can check that a unique property on the object exists before dealing with the object so typescript can deduce what type it is.
Example:
interface IObjectYo {
someProp: number
same: boolean
}
interface IDifObjYo {
otherProp: number
same: boolean
}
function example(someArg: IObjectYo | IDifObjYo) {
console.log(someArg.someProp) // tsc plains because someProp doesn't belong to IDifObjYo
if ('someProp' in someArg) {
console.log(someArg.someProp) // tsc knows it must be type IObjectYo because someProp only belongs to IObjectYo
} else {
console.log(someArg.otherProp) // tsc knows this is IDifObjYo because the first condition failed (which means it must be of type IDifObjYo)
}
if ('same' in someArg) {
console.log(someArg.someProp) // make sure the property is indeed unique between the possible types or tsc can't infer
}
}
In your case (and I'm not a React guy) you could do something like this:
type Team = {
name: string;
city: string
}
type Position = {
position: number;
}
const Component = () => {
const [list, setList] = useState<Array<Team | Position >>(teams)
list.map((item: Team | Position) => {
return 'name' in item ? (
<div>
<p>{item.name}</p>
<p>{item.city}</p>
</div>
) : (
<p>{item.position}</p>
)
})
}