I'm trying to render information from the "rest countries" api through a map, but my typescript doesn't recognize the type inside my array with the information.
errors : "Property 'name' does not exist on type 'never'."
"Property 'population' does not exist on type 'never'."
"Property 'region' does not exist on type 'never'."
"Property 'flags' does not exist on type 'never'."
import * as C from './styles';
import { useEffect, useState } from 'react';
import Input from '../../components/Input';
import { api } from '../../api';
import { CountriesTS } from '../../types/Countries';
import CountryItem from '../../components/CountryItem';
const Countries = () => {
const [countries, setCountries] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
getAllCountries()
}, [])
const getAllCountries = async () => {
setLoading(true);
const resultCountries = await api.getCountries();
setCountries(resultCountries);
setLoading(false);
console.log(countries);
}
return (
<C.CountriesArea>
<Input />
<div className="countries">
{loading &&
<div className=''>Carregando...</div>
}
{!loading &&
countries.map((item) => (
<CountryItem
name={item.name}
population={item.population}
region={item.region}
capital={item.capital}
flag={item.flags.png}
/>
))
}
</div>
</C.CountriesArea>
)
}
export default Countries
CountryItem folder:
import { CountryItemTS } from '../../types/CountryItem';
import { Link } from 'react-router-dom';
const CountryItem = ({name, population, region, capital, flag}: CountryItemTS) => {
return (
<C.CountryItem>
<Link to={`country/${name}`}>
<div className="img--area">
<img src={flag} alt={`Bandeira do País: ${name}`} />
</div>
<div className="data--area">
<p className="country--name">{name}</p>
<p>Population: <span>{population}</span></p>
<p>Region: <span>{region}</span></p>
<p>Capital: <span>{capital}</span></p>
</div>
</Link>
</C.CountryItem>
)
}
export default CountryItem
API folder:
import axios from "axios";
const http = axios.create({
baseURL: 'https://restcountries.com/v3.1/'
})
export const api = {
getCountries: async () => {
let response = await http.get('/all')
return response.data
},
getCountry: async (name: string) => {
let response = await http.get(`/name/${name}?fullText=true`)
return response.data
},
getCountryByCode: async (code: string) => {
let response = await http.get(`/alpha?codes=${code}`)
return response.data
}
}
Type CountryItemTS folder:
export interface CountryItemTS {
name: string,
capital: string,
population: number,
region: string,
flag: string,
}
CodePudding user response:
In "Countries" component , the initializing of countries state should be with type like this
const [countries, setCountries] = useState<CountryItemTS[]>([]);
If the keys received in countries
state are different as I can notice in line flag={item.flags.png}
,
then you can declare a new interface like this:-
interface ICountries extends CountryItemTS{
flags: { png: string };
}
CodePudding user response:
Since you're initiating countries
with an empty array, TypeScript don't know which type it is. Do the following to give countries
a type.
const [countries, setCountries] = useState<CountryItemTS[]>([]);