I’ve these 3 fields in my form (sku, sku_variation, name) and I want to use them to create a new product.
I came up with this solution recasting the parsedData
to unknown first but it looks completely bad practice.
export type TProduct = {
id: string,
sku: number,
skuVariation: number,
name: string,
}
export type TCreateProduct = Omit<TProduct, 'id'>;
const createProduct = async(parsedData:TCreateProduct) => {
fetch('http://localhost:3333/api/products/',{
method: 'POST',
body: JSON.stringify(parsedData)
})
return '';
}
const handleSubmit = (e:React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const form = new FormData(e.target as HTMLFormElement);
const parsedData = Object.fromEntries(form.entries()) as unknown as TCreateProduct;
createProduct(parsedData);
}
Without the as unknown as TCreateProduct
casting the error thrown in the createProduct
call as:
Argument of type '{ [k: string]: FormDataEntryValue; }' is not assignable to parameter of type 'TCreateProduct'.
Type '{ [k: string]: FormDataEntryValue; }' is missing the following properties from type 'TCreateProduct': sku, skuVariation, name
2
Answers
TypeScript is right to force you to do the hacky double cast as your cast is invalid. FormData is only going to have values of type string or File, but the TCreateProduct type has properties with number values. This means that if a key matches one of those properties with a number value then the type of the property in the resulting object would be incorrect.
If you change your type to be a record of strings, then you can remove the extra cast to unknown. Of course, you’ll probably have an issue with createProduct since the request body be serialized with values for sku and skuVariation encoded as strings.
Alternatively you can map the values, doing the appropriate transformations for number values. It won’t look as neat as doing Object.fromEntries(), but it’ll be the most accurate.
You can use a third-party library to act as a TypeGuard and values validator. There are some, like Joy and Zod. I will give you an example with Zod
Have in mind that
createProductSchema.parse
will throw an error if data is not correct