Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

284
Vistas
TypeScript: escribir un valor basado en una clave de objeto

Necesito ayuda en mi aventura de TypeScript.

Aquí está mi tipo de ejemplo:

 type Target = { names: string[] addresses: { location: string }[] };

Aquí está mi objeto de ejemplo:

 const myTarget: Target = { names: ["Alex", "Nico"], addresses: [ { location: "Miami", }, { location: "New York", }, ], };

Y aquí está mi ejemplo de función:

 const changeValue = ( key: keyof Target, value: string | Record<string, unknown> ) => { myTarget[key] = [...myTarget[key], value] } changeValue('names', 'Elvis') changeValue('addresses', { location: "Atlanta" })

Tengo un error en myTarget[key] que dice esto:

No se puede asignar el tipo '(cadena | Record<cadena, desconocido>)[]' para escribir 'cadena[] & { ubicación: cadena; }[]'.
No se puede asignar el tipo '(cadena | Record<cadena, desconocido>)[]' para escribir 'cadena[]'.
No se puede asignar el tipo 'cadena | Record<cadena, desconocido>' de tipo 'cadena'.
No se puede asignar el tipo 'Record<cadena, desconocido>' para escribir 'cadena' .ts(2322)

Por lo que entiendo es que, por ejemplo, TypeScript está probando todas las combinaciones, incluida la adición de un objeto a la matriz de names , que no es válida, o la adición de una cadena dentro de la matriz de addresses .

¿Puede alguien ayudarme a entender cuál es el problema y cómo puedo manejarlo? (el proyecto real es mucho más complicado, pero tal vez con este ejemplo lo entienda un poco...)

Muchas gracias.

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

En general, cuando desea pasar una clave de un tipo de objeto y un valor del tipo de esa clave, puede hacerlo así:

 const changeValue = <K extends keyof Target, V extends Target[K]>( key: K, value: V ) => { myTarget[key] = value; }

Es decir, le dices al compilador que value no solo es del mismo tipo que algún valor del objeto, sino del mismo tipo que el dado por key .

Sin embargo, aumentaste la dificultad jugando con arreglos. Hasta donde yo sé, no existe un tipo de utilidad para extraer el tipo de una matriz, así que escribí uno:

 type ArrayType<T> = T extends Array<infer U>? U : never;

Ahora podemos usarlo:

 const appendValue = <K extends keyof Target, V extends ArrayType<Target[K]>>( key: K, value: V ) => { myTarget[key] = [...myTarget[key], value] as Target[K]; }

Desafortunadamente, como puede ver, el compilador se confunde un poco acerca de la relación entre V[] y Target[K] , por lo que necesita la pista en forma de as .

Ahora las llamadas se compilan limpiamente:

 appendValue('names', 'Elvis') appendValue('addresses', { location: "Atlanta" })

Por cierto, haces algunas cosas en tu código de ejemplo (aunque quizás no en tu código real) que te recomiendo que no hagas.

Primero, tiene datos globales mutables , myTarget . Hic fons lacrimis , no hagas esto, en ningún idioma, si puedes evitarlo.

Además, mutar datos en general es una mala idea . Considere esto en su lugar:

 const appendValue = <K extends keyof Target, V extends ArrayType<Target[K]>>( target: Target, key: K, value: V ): Target => ({ ...target, [key]: [...myTarget[key], value] as Target[K] })
about 4 years ago · Juan Pablo Isaza Denunciar

0

¿Por qué tienes un error?

Puede encontrar la respuesta a esta pregunta aquí , aquí , aquí y en mi artículo aquí .

Usando este tipo string | Record<string, unknown> para el argumento de value no es seguro. Es mejor inferir el tipo de argumento key :

 const changeValue = <Key extends keyof Target>( key: Key, value: Target[Key][number] ) => { // error myTarget[key] = [...myTarget[key], value] }

Tiene un error aquí, porque no hay una correlación (dentro) del cuerpo de la función entre la key y el value . Tal correlación existe solo fuera de la función, es decir, cuando llamas a esta función.

Tenga en cuenta que la key sigue siendo un tipo de unión. Creo que vale la pena usar el enfoque inmutable:

 type Target = { names: string[] addresses: { location: string }[] }; const myTarget: Target = { names: ["Alex", "Nico"], addresses: [ { location: "Miami", }, { location: "New York", }, ], }; const withTarget = < Obj extends Record<string, unknown[]> >(target: Obj) => < Key extends keyof Obj >( key: Key, value: Obj[Key][number] ): Obj => ({ ...target, [key]: target[key].concat(value) }) const changeValue = withTarget(myTarget); const result = changeValue('names', 'Elvis')
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda