Errores típicos y tipado
Los fallos que todo el mundo comete con signals: copiar o desestructurar el valor y perder la reactividad, olvidar los paréntesis del getter, pasar el valor en vez de la función. Y cómo tiparlos bien en TypeScript: inferencia, el caso undefined de createSignal sin argumento, y los tipos Accessor y Setter en props.
Los cuatro clásicos que rompen la reactividad
Todos los fallos de reactividad con signals son variaciones de un mismo pecado —leer demasiado pronto y guardar el resultado— pero conviene tenerlos catalogados:
El caso de las props merece una nota: en Solid, props es un objeto reactivo (un proxy), y desestructurarlo con const { valor } = props evalúa valor una sola vez, perdiendo la reactividad igual que copiar un signal. Es el error más frecuente al llegar desde React, y su solución —acceder siempre como props.valor, o separar con splitProps y fijar defaults con mergeProps— es tema de un nivel propio. Lo mencionamos aquí porque comparte exactamente la misma raíz que copiar un getter.
// MAL: desconecta las props reactivasfunction Saludo(props: { nombre: string }) { const { nombre } = props; // foto return <p>Hola, {nombre}</p>; // no reacciona}// BIEN: accede en el punto de usofunction Saludo(props: { nombre: string }) { return <p>Hola, {props.nombre}</p>;}Tipar signals en TypeScript
Con un valor inicial, TypeScript infiere el tipo y rara vez necesitas anotar nada: createSignal(0) produce un Signal<number>, createSignal("") un Signal<string>. La inferencia es tu primera línea de defensa, porque convierte “pasé el tipo equivocado” en un error de compilación.
const [count, setCount] = createSignal(0); // Signal<number>setCount("x"); // Error de tipos: string no es asignable a numberCuando el valor inicial no basta para inferir el tipo que quieres —un array vacío, una unión, un objeto que admite null— pasa el parámetro de tipo explícito:
type Todo = { id: number; texto: string; hecho: boolean };const [todos, setTodos] = createSignal<Todo[]>([]); // no es never[]const [user, setUser] = createSignal<User | null>(null); // admite ambosPara tipar un signal que recibes —en las props de un componente o como argumento de una función— usa los tipos exportados por Solid. El getter es un Accessor<T> y el setter un Setter<T>; la tupla completa es un Signal<T>:
import type { Accessor, Setter } from "solid-js";function Panel(props: { count: Accessor<number>; setCount: Setter<number> }) { return ( <button onClick={() => props.setCount(c => c + 1)}> {props.count()} </button> );}Tipar la prop como Accessor<number> y no como number documenta en la firma que esperas una lectura reactiva, no una foto, y hace que pasar count() por error sea un fallo de compilación en vez de un bug silencioso. El sistema de tipos se convierte así en el guardián de la regla “pasa la función, no el valor”.