Estoy creando una aplicación en React Typescript y tengo un estado definido así:
const [products, setProducts] = useState({ fruits: [], veggies: [], herbs: [], }); Cuando quiero agregar un producto desde una HTML select , digamos una fruta, llamaré a lo siguiente en la función onChange :
addProduct("fruits", value); Donde la función addProduct se parece a la siguiente. Estoy usando productType como clave para acceder al tipo de producto específico en products :
const addProduct = (productType: string, value: string) => { setProducts((products) => ({ ...products, [productType]: [...products.productType, value], })); } Sin embargo, recibo este error (captura de pantalla adjunta al enlace): TS2339: la propiedad 'productType' no existe en el tipo '{ frutas: nunca []; verduras: nunca[]; hierbas: nunca[]; }'. donde ...products.productType está resaltado.
Intenté acceder a ...products.productType usando el identificador de signo de dólar, literales de plantilla, pero fue en vano. ¿Cómo puedo acceder a ...products.productType ? ¿Hay una sintaxis correcta para usar, o hay una solución pirateada para esto?
EDITAR: Gracias por las sugerencias sobre la definición de los tipos, lo tendré en cuenta. Sin embargo, creo que este es el problema de fondo:
"TS2339: Property 'productType' does not exist on type 'IState'". Si intento acceder a ...products.productType , no me lo permite porque productType no existe en el estado de mis products . ¿Cómo puedo hacer que busque el literal de cadena (que, en este ejemplo, es "frutas" )?
Recomendaré mantener 3 estados diferentes en lugar de usar solo uno. Eso será mucho más flexible y fácil de usar y comprender (para usted y otros desarrolladores que tocan su código).
En caso de que aún quiera hacerlo de esa manera, lo que le sucede es que TypeScript está inferring los tipos de sus valores iniciales, que son matrices vacías = never[] . Para solucionar esto, debe escribir su estado como:
interface IState { fruits: string[], // use whatever value it should be, I'm just guessing its a string veggies: string[], herbs: string[], } const [products, setProducts] = useState<IState>({ fruits: [], veggies: [], herbs: [], }); const addProduct = (productType: keyof IState, value: string) => { setProducts((products) => ({ ...products, [productType]: [...products[productType], value], })); }EDITAR : tenga en cuenta que hay 2 errores más
producType no debe ser de tipo cadena sino una clave de IStateHay algunas cosas mal con su código como @super mencionado, también debe corregirlas. En cuanto a la razón detrás del problema que está obteniendo, es porque está tratando de acceder a la propiedad productType del estado anterior usando products.productType .
La propiedad a la que está intentando acceder no existe, lo que está causando el problema y le está dando el error.
Para acceder a los valores de los estados antiguos para concatenar en la matriz de valores, cambie su código como se muestra a continuación,
setProducts((products) => ({ ...products, [productType]: [...products[productType], value], }));Esto debería solucionar su problema.
EDITAR
Después del cambio en el código para incluir tipos para el objeto de estado, la respuesta de @ toni proporciona el cambio que se necesitaba.