Error de TypeScript que no entiendo: Property 'nombre' does not exist on type 'never'
Lucía Ferrer@lucia_ferrer_dev
Holaaa! Llevo una hora con esto y me da vergüenza preguntarle otra vez a mi tech lead jajaja. Tengo esto en un componente:
const [usuarios, setUsuarios] = useState([])
useEffect(() => {
fetch('/api/usuarios')
.then(res => res.json())
.then(data => setUsuarios(data))
}, [])
return (
<ul>
{usuarios.map(u => <li key={u.id}>{u.nombre}</li>)}
</ul>
)
Y TypeScript me marca en rojo u.id y u.nombre:
Property 'nombre' does not exist on type 'never'.
He probado a poner any y se quita, pero mi tech lead me dijo en la review que nada de any xD. ¿Qué es "never" y por qué sale aquí? Explain me please como si tuviera 5 años!!
Accepted answer
¡Hola Lucía! Pregunta súper válida 💜
Cuando haces useState([]) TypeScript tiene que adivinar el tipo con lo único que le das: un array vacío. Un array vacío no tiene elementos, entonces TS dice "esto es un array de... nada", o sea never[]. Y claro, "nada" no tiene propiedad nombre.
La solución es decirle qué va a haber dentro:
interface Usuario {
id: number
nombre: string
}
const [usuarios, setUsuarios] = useState<Usuario[]>([])
Con eso ya te autocompleta u.nombre, y si escribes u.nombr te avisa. Bonus: res.json() devuelve any, así que si quieres ser estricta pon .then((data: Usuario[]) => setUsuarios(data)), o mejor valida con zod. Tu tech lead tiene razón con lo del any jaja
Get the best of #codigo_en_espanol weekly
One email each Monday with the most useful posts. No spam; unsubscribe in one click.
Comments
Sign in to join the conversation.
Sign in to commentAccepted answer
Sofía Ramírez@sofi_dev_mx
¡Hola Lucía! Pregunta súper válida 💜
Cuando haces useState([]) TypeScript tiene que adivinar el tipo con lo único que le das: un array vacío. Un array vacío no tiene elementos, entonces TS dice "esto es un array de... nada", o sea never[]. Y claro, "nada" no tiene propiedad nombre.
La solución es decirle qué va a haber dentro:
interface Usuario {
id: number
nombre: string
}
const [usuarios, setUsuarios] = useState<Usuario[]>([])
Con eso ya te autocompleta u.nombre, y si escribes u.nombr te avisa. Bonus: res.json() devuelve any, así que si quieres ser estricta pon .then((data: Usuario[]) => setUsuarios(data)), o mejor valida con zod. Tu tech lead tiene razón con lo del any jaja
Lucía Ferrer@lucia_ferrer_dev
OMG funcionaaa!! Y ahora entiendo lo de never, es como 'array de la nada' jajaja. Muchísimas gracias Sofía!! 🙏
Javier Montero@javi_montero
Lucía, en Java esto sería List<Usuario> usuarios = new ArrayList<>(); y el compilador tampoco te deja inventar. Los genéricos son tus amigos. Y pregúntale a tu tech lead las veces que haga falta, que para eso cobra más que tú.
Camilo Restrepo@camilo_parce
Buenísima la explicación de Sofi. Yo agrego: si el endpoint también lo controlan ustedes, compartan el tipo entre backend y frontend y se ahorran sustos
Bram Verhoeven@bram_on_a_bike
Used translate. Sofía is correct. Lucía, write the type the first time you create the state and TypeScript is quiet forever. Good that you did not use any. Lekker 🚲
Luis Treviño@luis_qa_mty
y cuando llegues a los tests, el tipo Usuario te sirve para los mocks. todo se conecta 🤣