Al trabajar con la interfaz FormData en JavaScript, donde los datos se añaden como pares clave/valor, no hay una forma integrada de hacer cumplir la seguridad de tipos en las claves que se añaden. Esto puede llevar a errores tipográficos, claves faltantes y errores inesperados en tiempo de ejecución. Pero en TypeScript, podemos resolver esto haciendo cumplir una validación estricta de claves.
Necesitaba esta solución yo mismo al enviar los valores de mi formulario a una API. Más tarde me di cuenta de que había cometido varios errores tipográficos en más de un par clave/valor que intentaba añadir a mi carga útil. Debido a que FormData acepta cualquier cadena como clave, pude pasar cadenas incorrectas y continuar con la solicitud a la API.
Después de que esto sucedió, busqué una forma de asegurarme de que TypeScript no permitiera esos errores.
Este artículo te mostrará cómo hacer que las claves de FormData
sean seguras en cuanto a tipos utilizando TypeScript.
Requisitos previos
Para aprovechar al máximo este artículo, deberías tener un entendimiento básico de lo siguiente:
-
Programación en JavaScript
-
Fundamentos de TypeScript, especialmente cómo funcionan las interfaces, tipos y el operador
keyof
-
la interfaz FormData
Si eres nuevo en TypeScript o FormData, te recomiendo que consultes la documentación oficial de TypeScript y la guía de MDN sobre FormData antes de continuar.
Paso 1: Define tus claves permitidas
La Forma Antigua
La forma predeterminada de agregar datos con FormData es hacerlo manualmente, con cadenas simples:
const payload = new FormData();
payload.append("id", "1122");
payload.append("name", "Clark Kent");
payload.append("agge", "36"); // Se permite un error de escritura en la clave
En el fragmento de código anterior, puedes ver que hubo un error de escritura al definir una clave para age
. Pero TypeScript no lo marcará como un error, y esto podría llevar a errores cuando estos datos se envíen con una solicitud a una API.
La Forma Mejor
En lugar de escribir manualmente las claves, defínelas en un esquema de objetos con una interfaz de TypeScript.
interface MyAllowedData {
id: number;
name: string;
age: number;
}
Alternativamente, puedes definirlas con tipos:
type MyAllowedData = {
id: number;
name: string;
age: number;
}
Puedes usar tipos o interfaces, es solo cuestión de preferencia. Puedes obtener más información sobre cómo difieren en este parque de juegos de documentación oficial de TypeScript.
A continuación, define un tipo de unión para cada clave en tu interfaz.
type MyFormDataKeys = keyof MyAllowedData
// esto es lo mismo que `type MyFormDataKeys = 'id' | 'name' | 'age'`
El operador keyof
ayuda a crear un tipo de unión de las claves de un tipo de objeto, por lo que resulta muy útil si no quieres definir manualmente un tipo de unión para un objeto más grande con muchas claves.
Paso 2: Crear una función auxiliar de añadir
Ahora que has definido tus claves estrictamente tipadas, el siguiente paso es crear una función auxiliar que asegure que solo se agreguen claves válidas a FormData.
function appendToFormData (formData: FormData, key: MyFormDataKeys, value: string) {
formData.append(key, value);
};
La función appendToFormData
toma tres argumentos. Así es cómo funciona todo:
-
El primer argumento,
formData
, es una instancia del objeto FormData. Aquí es donde se agregarán pares clave/valor antes de enviarlos en una solicitud API. -
El segundo argumento,
key
, es el nombre de la clave del campo que deseas agregar. Su tipo esMyFormDataKeys
, el tipo de unión que creamos para asegurarnos de que solo se agreguen esas claves que hemos definido a FormData. -
El tercer argumento es una cadena
value
que representa el valor que se añadirá con la clave.
Nota que FormData solo acepta string
y Blob
como tipos de valores en cada par clave/valor. En esta guía, solo trabajaremos con valores de tipo string, pero ten en cuenta que puedes usar valores de blob para adjuntar archivos a las solicitudes API.
Ahora, probemos la función:
const payload = new FormData();
appendToFormData(payload, "id", "19282"); // ✅ Permitido
appendToFormData(payload, "name", "Lenny Brown"); // ✅ Permitido
appendToFormData(payload, "age", "20"); // ✅ Permitido
appendToFormData(payload, "someOtherKey", "89"); // ❌ Error de TypeScript: El argumento de tipo 'someOtherKey' no es asignable.
Paso 3: Usa la función auxiliar después del envío del formulario
Ahora vamos a añadir nuestros campos a FormData antes de enviarlos a una API.
const handleSubmitForm = () => {
const payload = new FormData();
appendToFormData(payload, "id", "19282");
appendToFormData(payload, "name", "Lenny Brown");
appendToFormData(payload, "age", "20");
// Enviar carga útil a través de la API
fetch("/api/submit", { method: "POST", body: payload });
};
Adjuntando campos desde un objeto
Alternativamente, si ya tienes toda tu carga útil en un objeto, puedes evitar adjuntar cada campo uno por uno implementando la función de esta manera:
const handleSubmitForm = () => {
// todos tus campos en un objeto
const formValues: MyAllowedData = {
id: 1123,
name: 'John Doe',
age: 56
}
const payload = new FormData();
Object.entries(formValues).forEach(([key, value]) => {
appendToFormData(payload, key as MyFormDataKeys, `${value}`); // usa literales de plantilla para pasar el valor
});
// Enviar carga útil a través de la API
fetch("/api/submit", { method: "POST", body: payload });
};
En el fragmento anterior, estamos usando Object.entries
para iterar sobre cada par clave/valor en un objeto para que pueda ser añadido al objeto FormData. Tenga en cuenta que el valor en cada par, ya sea una cadena o un número, se pasa como una cadena usando plantillas de cadenas para evitar una discrepancia de tipo de TypeScript desde el argumento value
en nuestra función auxiliar.
Conclusión
Al aprovechar el operador keyof
de TypeScript, podemos hacer que FormData.append()
sea totalmente segura en cuanto a tipos. Esta técnica simple ayuda a prevenir discrepancias de clave y hace que sus solicitudes de API sean más confiables.
Hágame saber sus opiniones sobre el artículo y siéntase libre de hacer cualquier sugerencia que crea que podría mejorar mi solución.
¡Gracias por leer!
Source:
https://www.freecodecamp.org/news/how-to-enforce-type-safety-in-formdata-with-typescript/