Home > Mobile >  Property does not exist in typescript react
Property does not exist in typescript react

Time:06-16

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[]>([]);
  • Related